1

我从 asp.net mvc 4 框架中的单元测试开始。

我有一个包含基本 crud 方法和 save 方法的存储库。当我创建一个单元测试时,我创建一个测试存储库并测试是否添加了一个项目到集合中。一切都很顺利,但我无法测试保存方法是否被击中。

我尝试向测试存储库添加一个布尔属性,如果 .save() 被命中,该属性将设置为 true。但随后我需要更改界面以及数据库存储库。在我看来,这既不实用也不是最佳实践。

测试这个的最佳方法是什么?预先感谢您的回答。

我的代码:

假存储库:

public class TestUserRepository : IUserManagementRepository
    {
        /// <summary>
        /// entries used used for testing
        /// </summary>
        private List<User> _entities;

        /// <summary>
        /// constructor
        /// </summary>
        public TestUserRepository()
        {
            _entities = new List<User>();
            _entities.Add(new User
            {
                Id = 1,
                InsertDate = DateTime.Now,
                LastUpdate = DateTime.Now,
                Username = "TestUserName",
                Password = "TestPassword"
            });
        }
...

public void Create(User task)
        {
            _entities.Add(task);
        }

public void Save()
        {
            //do nothing
        }
    }

要测试的控制器:

[HttpPost]
        public ActionResult Create(User user)
        {
            if (ModelState.IsValid)
            {
                _repository.Create(user);
                _repository.Save();
                return RedirectToAction("Index");
            }
            else
            {
                return View(user);
            }

        }

和测试

[TestMethod()]
        public void CreateTest()
        {
            IUserManagementRepository repository = new TestUserRepository();
            UserController controller = new UserController(repository);
            User user = new User { Username = "UnitTestUserName", InsertDate = DateTime.Now, LastUpdate = DateTime.Now, Password = "Password" };
            ActionResult actionResult = controller.Create(user);
        User returnedUser = repository.FindBy(u => u.Username == "UnitTestUserName").First<User>();

            Assert.IsNotNull(actionResult);
            Assert.AreEqual(user, returnedUser);            
        }
4

1 回答 1

1

您必须注意不要编写一堆仅测试您的测试存储库的单元测试。

考虑以下场景:

  1. 您有一个服务方法,应该将项目添加到您的存储库。
  2. 您的单元测试调用此方法,并且您应该验证是否在存储库上调用了适当的“AddX”方法。

这是一个有效的单元测试场景,要对其进行测试,您可以使用您的测试存储库。由于它是您的测试对象,因此您可以完全控制它。您可以公开诸如“AddXMethodCallCount”之类的属性或类似的东西。

随着时间的推移,您会发​​现自己编写了很多几乎是样板的测试代码。我强烈推荐的替代方法是使用模拟框架:

https://stackoverflow.com/questions/37359/what-c​​-sharp-mocking-framework-to-use

这需要一些时间来适应,但是一旦你掌握了它,它将显着加快你的单元测试。

如果您还不想使用模拟,但仍想实现验证是否调用 Save() 的目标,我建议您添加一个公开的 SaveMethodCallCount 属性:

public class TestUserRepository : IUserManagementRepository
{

...


public SaveMethodCallCount {get; set;}

...
public void Save()
    {
        SaveMethodCallCount++;
    }
}

这行得通,因为在您的单元测试中,您实际上可以说:

TestUserRepository 存储库 = new TestUserRepository();

UserController 不关心,只要传入的参数实现了 IUserManagementRepository 接口即可。控制器通过接口与存储库对象交互,但单元测试不必这样做,并且作为测试类的 TestUserRepository 被允许具有更多功能,而不必通过接口公开。

所以你的测试可能看起来像:

[TestMethod()]
    public void CreateTest()
    {
        TestUserRepository repository = new TestUserRepository();
        UserController controller = new UserController(repository);
        User user = new User { Username = "UnitTestUserName", InsertDate = DateTime.Now, LastUpdate = DateTime.Now, Password = "Password" };
        ActionResult actionResult = controller.Create(user);
    User returnedUser = repository.FindBy(u => u.Username == "UnitTestUserName").First<User>();

        Assert.IsNotNull(actionResult);
        Assert.AreEqual(user, returnedUser);  
        Assert.AreEqual(1, repository.SaveMethodCallCount);
    }

为了使我的示例完整,让我向您展示如果您使用模拟框架(如 Moq)会是什么样子。您可以在此处查看更多示例。示例测试方法使用 Moq 和Arrange/Act/Assert,并且只测试一件事——调用 Create() 时调用 Save()。

[TestMethod()]
public void Test_SaveCalledWhenCreateCalled()
{    
    // Arrange
    // First, instead of creating an instance of your test class, you create a mock repository. 
    // In fact, you don't need to write any code, the mocking framework handles it. 
    var mockRepository = new Mock<IUserManagementRepository>();
    // and pass the mock repository (which implements the IUserManagementRepository) to your controller
    UserController controller = new UserController(mockRepository);

    // Act
    ActionResult actionResult = controller.Create(user);

    // Assert
    // see how easy it is to do with a mocking framework:
    mockRepository.Verify(rep => rep.Save(), Times.AtLeastOnce());
}
于 2012-08-10T16:14:07.970 回答