asp.net-mvc - 这个 TestMethod 有什么问题?

标签 asp.net-mvc unit-testing tdd

所以我想学习一点 TDD,并想看看我是否可以测试一个应该简单地返回一个 View 的索引操作。

测试没有通过,错误是

Test method Summumnet.Tests.Controllers.PhysicalTestsControllerTest.IndexShouldReturnView threw exception: System.ArgumentException: Expression is not a property access: c => c.FindById(1)

这是我的 Controller 操作代码:

[Authorize]
    [AllowedToEditEHR]
    public class PhysicalTestsController : Controller
    {
        private IUnitOfWork unitOfWork;
        private IRepository<EHR> ehrRepository;
        private const int PAGESIZE = 5;


        public PhysicalTestsController(IUnitOfWork unit)
        {
            unitOfWork = unit;
            ehrRepository = unitOfWork.EHRs;

        }

        public ActionResult Index(int ehrId, int? page)
        {
            EHR ehr = ehrRepository.FindById(ehrId);
            var physicaltests = ehr.PhysicalTests.Where(test => !test.IsDeleted).OrderByDescending(test => test.CreationDate);
            List<PhysicalTestListItem> physicalTestsVM = new List<PhysicalTestListItem>();
            Mapper.Map(physicaltests, physicalTestsVM);
            var paginatedTests = physicalTestsVM.ToPagedList(page ?? 0, PAGESIZE);
            return View(paginatedTests);
        }

这是测试

[TestClass]
    public class PhysicalTestsControllerTest
    {
        [TestMethod]
        public void IndexShouldReturnView()
        {
            // Arrange

            var mock = new Mock<ControllerContext>();
            mock.SetupGet(p => p.HttpContext.User.Identity.Name).Returns("nacho");
            mock.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(true);

            var mockUnitofWork = new Mock<IUnitOfWork>();
            var mockEhrRepository = new Mock<IRepository<EHR>>();
            mockEhrRepository.SetupGet(c => c.FindById(1)).Returns(new EHR { PhysicalTests = new List<PhysicalTest>()});
            mockUnitofWork.SetupGet(p=>p.EHRs).Returns(mockEhrRepository.Object);
            PhysicalTestsController controller = new PhysicalTestsController(mockUnitofWork.Object);
            controller.ControllerContext = mock.Object;

            // Act
            ViewResult result = controller.Index(1, 0) as ViewResult;

            // Assert
            Assert.IsNotNull(result);
        }

最佳答案

几点建议:

  1. 你不需要模拟 HttpContext对于这个测试。当然,你有一个 Authorize属性,但是当您对 Controller 进行单元测试时,操作过滤器不会运行。因此,您可以假设用户将通过身份验证和授权。

  2. SetupGet是,我相信,相当过时。您应该考虑使用 Setup而是:

    mockUnitofWork.Setup(p => p.EHRs).Returns(mockEhrRepository.Object);
    

    这实际上是导致您的错误的原因,因为 SetupGet只能用于属性,而 Setup可用于或多或少的任何东西。从 FindById不是一个属性(它是一个方法),你会得到那个错误。

  3. 在设置函数调用时,如果不给出准确的输入参数,而是指定输入参数必须满足的条件,通常会得到更好的结果。当您传入两个相同但独立的类实例并期望它们相同时,这可以避免意外且通常难以跟踪的测试错误。

    在起订量中,您可以使用 It 上的静态方法去做这个。如果您想允许任何 int ,就说It.IsAny<int>()代替整数参数。如果您想具体一点,可以使用 lambda 表达式来声明何时应用该行为,使用 It.Is<int>(i => someCondition(i)) .所以而不是.Setup(c => c.FindById(1))你说

    mockEhrRepository.Setup(r => r.FindById(It.Is<int>(i => i == 1)).Returns(...)
    

    对于值类型,这没有任何区别,但我认为这是一个好习惯。我通常选择不关心 哪个 整数,这样可以稍微简化设置表达式:

    mockEhrRepository.Setup(r => r.FindById(It.IsAny<int>()).Returns(...)
    

但要明确一点:您在这篇文章中需要做的唯一一件事就是改变 SetupGetSetup

关于asp.net-mvc - 这个 TestMethod 有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7072051/

相关文章:

django - TDD Django 测试似乎跳过了 View 代码的某些部分

ruby-on-rails - capybara 测试 javascript 无法刷新 .count

mocking - 如何使用 Jest 模拟对象中的特定函数?

asp.net-mvc - 更改 asp.net mvc 应用程序名称

c# - 覆盖 MVC 中的最大长度错误消息

java - mockito 中的 doAnswer - 什么时候是惰性评估,什么时候是急切的?

c# - 使用断言的单元测试用例

c# - ASP.Net MVC 5 Forms Authentication 在代码后面获取用户名

javascript - ajaxSetup beforeSend 仅在第一次单击按钮时被调用

java - 代码分支应该应用哪些单元测试组合?