【问题标题】:Testing a controllers parameterless constructor测试控制器无参数构造函数
【发布时间】:2013-01-19 05:31:21
【问题描述】:

我的应用程序中有一个相当基本的 HomeController,我为它编写了一个测试类。在我的测试类上运行代码覆盖率分析后,我意识到我没有对默认构造函数进行任何测试。

这是我的 HomeController

public class HomeController : BaseController
{
    private INewsRepository _newsRepository;
    private INewsletterRepository _newsletterRepository;
    private string _currentLanguage;

    public HomeController()
    {
        _newsRepository = NewsRepository.Current;
        _newsletterRepository = NewsletterRepository.Current;
        _currentLanguage = ApplicationConfig.Current.CurrentLanguage;
    }

    public HomeController(INewsRepository newsRepository, INewsletterRepository newsletterRepository, string currentLanguage)
    {
        _newsRepository = newsRepository;
        _newsletterRepository = newsletterRepository;
        _currentLanguage = currentLanguage;
    }

    public ActionResult Index()
    {
        return View();
    }

    public ActionResult LatestNews()
    {
        return View(_newsRepository.ListAll().Where(n => n.LanguageKey.ToLower() == _currentLanguage.ToLower()).OrderByDescending(n => n.Date).Take(10));
    }

    public ActionResult LatestNewsletters()
    {
        return View(_newsletterRepository.ListAll().Where(n => n.LanguageKey.ToLower() == _currentLanguage.ToLower()).OrderByDescending(n => n.Date).Take(10));
    }
}

这是我的测试类:

[TestClass]
public class HomeControllerTest
{
    private INewsletterRepository _mockNewsletterRepostiory = null;
    private INewsRepository _mockNewsRepostiory = null;
    private List<News> _fakeNewsList = new List<News> { 
            new News{Id = 0, Title = "some title", Date = new DateTime(1989, 2, 19), LanguageKey = "fa", Description = "some description"}, 
            new News{Id = 1, Title = "some title", Date = new DateTime(1989, 2, 20), LanguageKey = "fa", Description = "some description"}, 
            new News{Id = 2, Title = "some title", Date = new DateTime(1989, 2, 21), LanguageKey = "fa", Description = "some description"}, 
            new News{Id = 3, Title = "some title", Date = new DateTime(1989, 2, 22), LanguageKey = "fa", Description = "some description"}
        };
    private List<Newsletter> _fakeNewsletterList = new List<Newsletter>
        {
            new Newsletter{ Id = 0, Description = "some description", UrlKey = "first-newsletter", Title = "some title", SendDate = null, NewsletterContents = null, LanguageKey = "fa", Date = new DateTime(1989, 2, 19) },
            new Newsletter{ Id = 1, Description = "some description", UrlKey = "first-newsletter", Title = "some title", SendDate = null, NewsletterContents = null, LanguageKey = "fa", Date = new DateTime(1989, 2, 20) },
            new Newsletter{ Id = 2, Description = "some description", UrlKey = "first-newsletter", Title = "some title", SendDate = null, NewsletterContents = null, LanguageKey = "fa", Date = new DateTime(1989, 2, 21) },
            new Newsletter{ Id = 3, Description = "some description", UrlKey = "first-newsletter", Title = "some title", SendDate = null, NewsletterContents = null, LanguageKey = "fa", Date = new DateTime(1989, 2, 22) }
        };

    [TestInitialize]
    public void Setup()
    {
        // Mock News Repository            
        var mockNewsRepository = MockRepository.GenerateStub<INewsRepository>();
        mockNewsRepository.Stub(m => m.ListAll()).Return(_fakeNewsList.AsQueryable());

        // Mock Newsletter Repository
        var mockNewsletterRopository = MockRepository.GenerateStub<INewsletterRepository>();
        mockNewsletterRopository.Stub(m => m.ListAll()).Return(_fakeNewsletterList.AsQueryable());

        _mockNewsletterRepostiory = mockNewsletterRopository;
        _mockNewsRepostiory = mockNewsRepository;
    }

    [TestMethod]
    public void IndexReturnsView()
    {
        // Arrange
        HomeController homeController = new HomeController(_mockNewsRepostiory, _mockNewsletterRepostiory, "fa");
        // Act
        ViewResult result = homeController.Index() as ViewResult;
        // Assert
        Assert.AreEqual("", result.ViewName);
    }

    [TestMethod]
    public void LatestNewsReturnsCorrectObject()
    {
        // Arrange
        HomeController homeController = new HomeController(_mockNewsRepostiory, _mockNewsletterRepostiory, "fa");
        // Act
        ViewResult result = homeController.LatestNews() as ViewResult;
        // Assert            
        Assert.IsNotNull(result.ViewData.Model, "Result model is not null.");
        Assert.IsTrue(_fakeNewsList.OrderByDescending(n => n.Date).SequenceEqual(result.ViewData.Model as IQueryable<News>), "Model is correct");
    }

    [TestMethod]
    public void LatestNewslettersReturnsCorrectObject()
    {
        // Arrange
        HomeController homeController = new HomeController(_mockNewsRepostiory, _mockNewsletterRepostiory, "fa");
        // Act
        ViewResult result = homeController.LatestNewsletters() as ViewResult;
        // Assert            
        Assert.IsNotNull(result.ViewData.Model, "Result model is not null.");
        Assert.IsTrue(_fakeNewsletterList.OrderByDescending(n => n.Date).SequenceEqual(result.ViewData.Model as IQueryable<Newsletter>), "Model is correct");
    }
}

首先我真的需要测试这个构造函数吗? 其次,将 _newsRepository 和其他人设为 public 和 readonly 然后在构造控制器后编写测试方法来检查它们的类型是否是一种好习惯?

【问题讨论】:

    标签: asp.net-mvc unit-testing


    【解决方案1】:

    我建议为构造函数编写测试的唯一原因是您是否非常关心获得尽可能多的代码覆盖率。测试您可以创建控制器实例的事实以及在 ctor 中创建的每个对象的实例是否有效并不是一个非常有价值的测试。我会说这是浪费时间。

    所以,对于您的第一个问题,我建议您不要担心对 ctor 进行单元测试。如果 ctor 中存在问题,那么您将通过其他单元测试很快注意到它,正如我在下一条评论中所解释的那样。

    至于使存储库类公开和只读,我不建议这样做。关于单元测试,您真正需要关注的是控制器的功能,尤其是使用在 ctor 中创建的对象的方法。那是你需要集中精力的地方。这些测试将告诉您这些对象的 ctor 中是否存在问题。

    【讨论】:

    • ctorcontrollerconstructor 的简写吗?
    • ctorconstructor 的简写。
    • 谢谢杰森。这有很大帮助:-)
    • @JasonEvans “如果 ctor 中有探针,您会通过其他单元测试注意到”:如果没有单元测试使用无参数 ctor 怎么办?在我的例子中,我有只使用依赖注入 ctor 的测试,并且没有检查(甚至是被动地)无参数 ctor 存在。我在尝试运行应用程序时遇到了问题,因为某些控制器错过了这些,因此 MVC 框架无法实例化它们。这里应该做什么?检查类是否有无参数 ctor 的测试?
    • 除非无参数构造函数的执行有一些副作用,例如设置/更改对象的状态,否则我不会考虑编写专注于无参数 ctor 的单元测试。此评论对您有帮助吗?
    猜你喜欢
    • 2013-07-01
    • 2023-04-03
    • 1970-01-01
    • 2022-10-15
    • 1970-01-01
    • 1970-01-01
    • 2013-03-08
    • 1970-01-01
    • 2019-07-12
    相关资源
    最近更新 更多