unit-testing - 在单元测试中,您是否验证和断言?

标签 unit-testing moq

我在我的单元测试项目中使用 Moq。我在网上看到的大多数单元测试示例都以 someMock.VerifyAll(); 结尾我想知道在VerifyAll()之后断言是否可以.例如,

//Arrange
var student = new Student{Id = 0, Name="John Doe", IsRegistered = false};
var studentRepository = new Mock<IStudentRepository>();
var studentService= new StudentService(studentRepository.Object);

//Act
studentService.Register(student);  //<-- student.IsRegistered = true now.

//Verify and assert
studentRepository.VerifyAll();
Assert.IsTrue(student.IsRegistered);

任何想法?谢谢你。

最佳答案

不,您不应该同时使用两者 在大多数情况下(总是有异常(exception))。这样做的原因是,出于可维护性、可读性和其他一些原因,您应该在测试中只测试一件事。因此,它应该在您的测试中使用 Verify(VerifyAll) 或 Assert,并相应地命名您的测试。

看看 Roy Osherove 关于它的文章:

http://osherove.com/blog/2005/4/3/a-unit-test-should-test-only-one-thing.html
VerifyAll用于确保调用某些方法以及调用次数。您使用 mocks为了那个原因。
Assert用于验证从您正在测试的方法返回的结果。您使用 Stubs为了那个原因。

Martin fowler 有一篇很棒的文章解释了模拟和 stub 之间的区别。如果您了解它,您将更好地了解其中的区别。

http://martinfowler.com/articles/mocksArentStubs.html

更新:按照下面评论中的要求,使用 Moq 的模拟 vs stub 示例。我使用过验证,但您也可以使用 VerifyAll。

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
... 

[TestClass]
public class UnitTest1
{
    /// <summary>
    /// Test using Mock to Verify that GetNameWithPrefix method calls 
    /// Repository GetName method once when Id is greater than Zero
    /// </summary>
    [TestMethod]
    public void GetNameWithPrefix_IdIsTwelve_GetNameCalledOnce()
    {
        // Arrange 
        var mockEntityRepository = new Mock<IEntityRepository>();
        mockEntityRepository.Setup(m => m.GetName(It.IsAny<int>()));

        var entity = new EntityClass(mockEntityRepository.Object);
        // Act 
        var name = entity.GetNameWithPrefix(12);
        // Assert
        mockEntityRepository.Verify(
            m => m.GetName(It.IsAny<int>()), Times.Once);
    }

    /// <summary>
    /// Test using Mock to Verify that GetNameWithPrefix method 
    /// doesn't calls Repository GetName method when Id is Zero
    /// </summary>
    [TestMethod]
    public void GetNameWithPrefix_IdIsZero_GetNameNeverCalled()
    {
        // Arrange 
        var mockEntityRepository = new Mock<IEntityRepository>();
        mockEntityRepository.Setup(m => m.GetName(It.IsAny<int>()));
        var entity = new EntityClass(mockEntityRepository.Object);
        // Act 
        var name = entity.GetNameWithPrefix(0);
        // Assert
        mockEntityRepository.Verify(
            m => m.GetName(It.IsAny<int>()), Times.Never);
    }

    /// <summary>
    /// Test using Stub to Verify that GetNameWithPrefix method
    /// returns Name with a Prefix
    /// </summary>
    [TestMethod]
    public void GetNameWithPrefix_IdIsTwelve_ReturnsNameWithPrefix()
    {
        // Arrange 
        var stubEntityRepository = new Mock<IEntityRepository>();
        stubEntityRepository.Setup(m => m.GetName(It.IsAny<int>()))
            .Returns("Stub");
        const string EXPECTED_NAME_WITH_PREFIX = "Mr. Stub";
        var entity = new EntityClass(stubEntityRepository.Object);
        // Act 
        var name = entity.GetNameWithPrefix(12);
        // Assert
        Assert.AreEqual(EXPECTED_NAME_WITH_PREFIX, name);
    }
}

public class EntityClass
{
    private IEntityRepository _entityRepository;
    public EntityClass(IEntityRepository entityRepository)
    {
        this._entityRepository = entityRepository;
    }
    public string Name { get; set; }
    public string GetNameWithPrefix(int id)
    {
        string name = string.Empty;
        if (id > 0)
        {
            name = this._entityRepository.GetName(id);
        }
        return "Mr. " + name;
    }
}

public interface IEntityRepository
{
    string GetName(int id);
}

public class EntityRepository:IEntityRepository
{
    public string GetName(int id)
    {
        // Code to connect to DB and get name based on Id
        return "NameFromDb";
    }
}

关于unit-testing - 在单元测试中,您是否验证和断言?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20863180/

相关文章:

c# - 如何从方法设置模拟数据而不将参数传递给方法

java - Junit 测试 Map<String, List<String>> 的 java.lang.NullPointerException

ruby-on-rails - Mock Sequel 连接到 Oracle 数据库

c# - 如何在单元测试中最小化 NetworkStream?

javascript - 如何让用户可以从 cli 安装我的测试包?

c# - 模拟服务调用对象返回 null

c# - 如何验证调用了一个方法?

unit-testing - WebStorm 运行所有 dart 单元测试

c# - 如何从集成测试将文件上传到端点

c# - 如何在单元测试中处理 try-catch block ?