测试异步方法会产生奇怪的结果
问题描述:
当我正常运行测试代码时,NUnit通知我测试失败。 result.Contacts
的值是3,而不是预期的1.当测试代码在测试代码中的assert语句中带有断点时运行时,测试不会失败。我怀疑这是与多线程相关的问题。测试异步方法会产生奇怪的结果
这是我的测试代码
[Test]
public async Task Method_Scenario_IncreasesCount()
{
// Arrange
const int employeeId = 1;
const string managerId = "asdf";
// Act
var result = await _uut.Contact(managerId , employeeId);
// Assert
Assert.That(result.Contacts, Is.EqualTo(1));
}
这是测试下的代码
public async Task<MyObject> Contact(string managerId, int employeeId)
{
var today = DateTime.UtcNow.Date;
var myStoredObject = _myObjectRepository.GetAll().Include(p => p.Employee).First(x => x.Employee.Id == employeeId);
myStoredObject.Contacts += 1;
myStoredObject.LastContact = today;
var dates = new List<DateTime>
{
myStoredObject.FirstDate,
myStoredObject.SecondDate,
myStoredObject.ThirdDate
};
if (!dates.Contains(today))
{
await _logging.Log(myStoredObject, Log.Extra);
await _myObjectRepository.UpdateAsync(myStoredObject);
}
return myStoredObject;
}
的_myObjectRepository
和_logging
对象使用Moq
嘲笑;而且myStoredObject
是由我预定义的,所以我知道联系人的值是0开始的。
为什么只有在断言语句中使用断点时才通过测试?我该如何解决这个问题?
编辑
我用Moq
要做到这一点也尝试:
_mock.Verify(r => r.UpdateAsync(It.Is<MyObject>(m => m.Contacts == 1)));
但是,这也将失败,与MockException说:
预期在模拟上至少调用一次,但从未执行过。
然而,如果我通过程序步骤,我可以看到,这个方法称为带有MyObject
具有Contacts = 1
。
答
很难说没有看到您的[SetUp]
代码可能会导致您的问题。我注意到你的模拟和被测试单元是成员变量 - 也许在与另一个测试共享状态时出现问题。我能够编写相同的测试,并且一致地通过
[Test]
public async Task Method_Scenario_IncreasesCount()
{
// Arrange
const int employeeId = 55378008;
var existingEntity = new MyObject {Employee = new Employee {Id = employeeId}};
var repo = Mock.Of<IMyObjectRepo>(r => r.GetAll() == new[] {existingEntity}.AsQueryable());
var uut = new MyUut(repo, Mock.Of<ILog>());
// Act
var entity = await uut.Contact(string.Empty, employeeId);
// Assert
Assert.That(entity.Contacts, Is.EqualTo(1));
Mock.Get(repo).Verify(r => r.UpdateAsync(entity));
}
这就解决了这个问题。非常好发现!该对象在我的测试类的构造函数中初始化。我把它移到了setup方法中,现在一切都按预期工作。但是我仍然不明白为什么当我用调试器遍历代码时它会通过。 –