unit-testing – 验证在单元测试中是否调用了一个方法或另一个方法

例:

public bool Save(MyObj instance)
{
    if (instance.IsNew)
    {
        this.repository.Create(instance);
    }
    else
    {
        this.repository.Update(instance);
    }
}

如何在Moq中创建一个用于验证的测试:

>正在阅读财产IsNew
>已调用Create()或Update()

最佳答案
脱离我的头顶:
验证是否正在读取IsNew属性:

var mock = new Mock<MyObj>();
mock.Setup(m => m.IsNew).Returns(true).Verifiable();
//...
sut.Save(mock.Object);
//...
mock.Verify();

在上面的示例中,IsNew属性将返回true,因此将采用Create路径.

要验证是否已调用Create或Update方法,您需要对该功能进行一些挂钩.看起来Repository是一个静态类,在这种情况下你不能用Test Double替换它,但我可能会以错误的方式读取你的代码……如果你可以用Test Double(Mock)替换它,您可以使用与上述相同的原则.

如果您可以在调用Save方法后检查存储库的状态,您可以通过State-Based Testing告诉我遵循了哪两个代码路径.

如果两个代码路径的结果之间没有外部可观察到的差异,那么最好不要测试这个特定的实现细节.它可能会引导你走向一种称为Overspecified Test的反模式 – 你可以在优秀的书籍xUnit Test Patterns中阅读更多关于这种反模式和许多其他单元测试相关的东西.

编辑:
可以使用相同的方式测试存储库:

var myObjMock = new Mock<MyObj>();
myObjMock.Setup(m => m.IsNew).Returns(true);

var repositoryMock = new Mock<Repository>();
repositoryMock.Setup(m => m.Create(myObjMock.Object)).Verifiable();

var sut = new SomeClass(repositoryMock.Object);
sut.Save(myObjMock.Object);

repositoryMock.Verify();

对Verifiable的调用是关键.没有它,Moq的默认行为是尽可能地做到最好,尽可能不抛出任何异常.

当您调用Verifiable时,您会指示模拟器期望该特定行为.如果在调用Verify时未满足该期望,则会引发异常,从而使测试失败.

转载注明原文:unit-testing – 验证在单元测试中是否调用了一个方法或另一个方法 - 代码日志