2015-06-21 63 views
2

当我正常运行测试代码时,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

回答

2

很难说没有看到您的[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)); 
} 
+0

这就解决了这个问题。非常好发现!该对象在我的测试类的构造函数中初始化。我把它移到了setup方法中,现在一切都按预期工作。但是我仍然不明白为什么当我用调试器遍历代码时它会通过。 –

相关问题