什么是使用Stubs和Mocks的正确方法?

Aca*_*uza 11 .net c# testing unit-testing mocking

这是我的例子:

[TestMethod]
public void NewAction_should_return_IndexAction()
{
    NewViewModel viewModel = new NewViewModel()
    {
        Name = "José Inácio Santos Silva",
        Email = "joseinacio@joseinacio.com",
        Username = "joseinacio"
    };

    //IsUserRegistered is used to validate Username, Username is unique.
    _mockAuthenticationService.Setup(x => x.IsUserRegistered(viewModel.Username )).Returns(false);

    //IsUserRegistered is used to validate Email, Email is unique.
    _mockUsuarioRepository.Setup(x => x.GetUserByEmail(viewModel.Email));
    _mockDbContext.Setup(x => x.SaveChanges());
    _mockUsuarioRepository.Setup(x => x.Add(It.IsAny<User>()));

    _userController = new UserController(_mockUsuarioRepository.Object, _mockDbContext.Object, _mockAuthenticationService.Object);

    ActionResult result = _userController.New(viewModel);

    result.AssertActionRedirect().ToAction("Index");

    _mockAuthenticationService.VerifyAll();
    _mockUsuarioRepository.VerifyAll();
    _mockDbContext.VerifyAll();
}
Run Code Online (Sandbox Code Playgroud)

我已经阅读了一些教程,他们说每次测试我们应该使用一个模拟.

但看看我的测试,它使用3次嘲讽,检查我的动作是否正常工作我需要检查这3个嘲讽,不同意?

如何以正确的方式进行此测试?

Mon*_*ong 4

每个单元测试应该只测试一件事。

在单元测试中,您正在测试三个模拟对象。如果mockAuthenticationService失败,则会报告此情况并且单元测试将在那里停止。其他 Mock 对象的任何错误都不会报告并被有效隐藏。

在这种情况下,您应该创建三个单元测试,并在每个单元测试中仅验证一个 Mock 对象。其余的仅用作存根。(存根与 Mock 对象完全相同,只是您最后不对其调用VerifyAll)

为了避免重复和浪费精力,您应该重构该单元测试,以便大部分代码位于单独的方法中。三个单元测试中的每一个都调用此方法,然后验证单个 Mock。

您还需要进行测试以确保调用正确的重定向。这也应该在单独的测试中进行。

很简单:

[TestMethod]
public void NewAction_should_checkUserRegistered()
{
    SetupTest();
    _mockAuthenticationService.VerifyAll();
}

[TestMethod]
public void NewAction_should_GetUserByEmail()
{
    SetupTest();
    _mockUsuarioRepository.VerifyAll();
}

[TestMethod]
public void NewAction_should_SaveDBContext()
{
    SetupTest();
    _mockDbContext.VerifyAll();
}

[TestMethod]
public void NewAction_should_return_Redirects_Action()
{
    var novoActionResult = SetupTest();
    novoActionResult.AssertActionRedirect().ToAction("Index");
}
Run Code Online (Sandbox Code Playgroud)