示例:
public bool Save(MyObj instance)
{
if (instance.IsNew)
{
this.repository.Create(instance);
}
else
{
this.repository.Update(instance);
}
}
如何在Moq中创建一个验证:
的测试IsNew
Create()
或Update()
答案 0 :(得分:3)
脱离我的头顶:
验证是否正在读取IsNew
属性:
var mock = new Mock<MyObj>();
mock.Setup(m => m.IsNew).Returns(true).Verifiable();
//...
sut.Save(mock.Object);
//...
mock.Verify();
在上面的示例中,IsNew
属性将返回true
,因此将创建“创建”路径。
要验证是否已调用Create或Update方法,您需要对该功能进行一些挂钩。看起来Repository是一个静态类,在这种情况下你不能用Test Double替换它,但我可能会以错误的方式读取你的代码......如果你可以用Test Double(Mock)替换它,您可以使用与上述相同的原则。
如果您可以在调用Save方法后检查存储库的状态,您可以通过基于状态的测试告诉我们遵循了哪两个代码路径。
如果两个代码路径的结果之间没有外部可观察的差异,那么最好不要测试这个特定的实现细节。它可能会引导你走向一种称为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时未满足该期望,则会抛出异常,从而使测试失败。
答案 1 :(得分:3)
不幸的是我自己有一个解决方案。
您所要做的就是拥有一个设置为0的本地int
变量,然后模拟增量。最后,您必须检查其名称是否大于0(或者恰好为1,具体取决于问题)。
// Arrange
int count = 0;
Mock<Repository> mock = new Mock<Repository>();
mock.Setup<bool>(m => m.Create(It.IsAny<MyObj>())).Callback(() => count++);
mock.Setup<bool>(m => m.Update(It.IsAny<MyObj>())).Callback(() => count++);
// Act
...
// Assert
Assert.AreEqual(count, 1);
将有两个测试。一个将属性IsNew
设置为true
,另一个将其设置为false
。