我正在创建几个单元测试,我想验证是否用我期望其属性的参数调用了一个方法。
因此,考虑到这个非常简单的系统:
public class Employee
{
public bool IsEmployed { get; set; }
}
public class DataStore
{
public void UpdateEmployee(Employee obj)
{
// Save in DB
}
}
public interface IDataStore
{
void UpdateEmployee(Employee employee);
}
public Employee FireEmployee(IDataStore dataStore, Employee employee)
{
employee.IsEmployed = false;
dataStore.UpdateEmployee(employee);
return employee;
}
我想验证
DataStore.UpdateEmployee()
属性设置为false时是否调用了Employee.IsEmployed
方法。所以这是我认为应该完成同一件事的两个测试用例。[Test]
public void TestViaVerify()
{
//Arrange
Mock<IDataStore> dataStore = new Mock<IDataStore>();
var robert = new Employee { IsEmployed = true };
//Act
FireEmployee(dataStore.Object, robert);
//Assert
dataStore.Verify(x => x.UpdateEmployee(It.Is<Employee>(e => e.IsEmployed == false)), Times.Once);
}
[Test]
public void TestViaSetupVerifyAll()
{
//Arrange
Mock<IDataStore> dataStore = new Mock<IDataStore>();
dataStore.Setup(x => x.UpdateEmployee(It.Is<Employee>(e => e.IsEmployed == false)));
var robert = new Employee { IsEmployed = true };
//Act
FireEmployee(dataStore.Object, robert);
//Assert
dataStore.VerifyAll();
}
给定系统的当前代码,两个测试均按预期通过。
现在说另一个开发人员出现了,并在
Employee.IsEmployed = false;
方法之后意外移动了DataStore.UpdateEmployee()
的设置。现在,在那种情况下,我希望测试失败,因为该雇员不会在数据库中标记为失业。public Employee FireEmployee(IDataStore dataStore, Employee employee)
{
dataStore.UpdateEmployee(employee);
employee.IsEmployed = false;
return employee;
}
现在,当我运行测试时:
TestViaVerify 通过
TestViaSetupVerifyAll 失败
我原本以为这两个方法都会失败,但对于
TestViaVerify()
方法而言,该方法中的lambda会在测试结束时执行,其中Employee.IsEmployed
已设置为false。有没有一种方法可以仅通过使用Verify方法来完成我想要的?不必执行安装程序...
VerifyAll
吗?如果没有,我将使用TestViaVerifyAll()
方法。 最佳答案
老实说,距离我上次使用moq
源代码更新的时间已经超过2年了。 Verify
和VerifyAll
都基于捕获到的所有伪实例调用(包括参数)。Verify
将查找方法/属性调用并验证捕获的调用(及其捕获的参数),而VerifyAll
将采用所有设置方法,并且与Verify
方法相同。
由于捕获的参数是ByRef
参数,并且如果最后一段仍然有意义,则可以通过在调用robert.IsEmployed = true;
/Verify
之前添加VerifyAll
来导致UT失败:
[Test]
public void TestViaVerify()
{
....
robert.IsEmployed = true; // will make this UT to failed
//Assert
dataStore.Verify(x => x.UpdateEmployee(It.Is<Employee>(e => e.IsEmployed == false)), Times.Once);
}
[Test]
public void TestViaSetupVerifyAll()
{
....
robert.IsEmployed = true; // will make this UT to failed
//Assert
dataStore.VerifyAll();
}
我认为过去我回答过类似的问题(带有更多示例),因此解决该问题的方法是
Setup
和Callback
之间的结合,因为我不喜欢使用VerifyAll
模式:....
var invokedCorrectly = false;
dataStore.Setup(x => x.UpdateEmployee(It.Is<Employee>(e => e.IsEmployed == false)))
.Callback<Employee>(x=> invokedCorrectly = true);
//Act
FireEmployee(dataStore.Object, robert);
//Assert
Assert.IsTrue(invokedCorrectly);
关于c# - Verify()和Setup()... VerifyAll()之间的最小起订量,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54797998/