Moq为异步事件监听器提升

时间:2017-12-13 03:59:55

标签: c# wpf unit-testing moq

在WPF中,我试图使用moq来引发一个异步侦听器挂钩的事件:

我的代码:

 public class Provider
    {
       private IService _service
       public Provider(IService service)
       {
         _service = service;
         _service.OnResultsChanged += ChangeResults;
       }

       private async void ChangeResults(List resultsAdded)
       {
         await Task.Run(() => HasResults = true;)
       }
   }

为了简化,我将hasresults设置为true,但我确实将项添加到列表中,因为此操作可能需要一段时间,我在新任务中执行此操作。在我的测试中,以下失败,因为它不等待DoSomething执行:

我的测试:

[Test]
public void Test()
{
//Arrange
var serviceMock = new Mock<IService>();
var systemUnderTest = new Provider(serviceMock .Object);

//Act
serviceMock.Raise(mock => mock.OnResultsChanged += null);

//Assert
Assert.IsTrue(systemUnderTest.HasResults);
}

是否可以告诉mock.raise等待我的事件监听器的执行?

谢谢!

1 个答案:

答案 0 :(得分:0)

您也可以将测试转换为异步,并等待延迟任务以允许异步事件处理程序执行其功能。

例如,以下测试使用偶数处理程序中的延迟来模拟潜在的长时间运行任务。

通过将测试转换为异步并等待引发的事件,断言能够被断言。

public interface IService {
    event EventHandler OnResultsChanged;
}

public class Provider {
    private IService _service;
    public Provider(IService service) {
        _service = service;
        _service.OnResultsChanged += ChangeResults;
    }

    private async void ChangeResults(object sender, EventArgs e) {
        await Task.Delay(200); //<-- simulate delay
        await Task.Run(() => HasResults = true);
    }

    public bool HasResults { get; set; }
}

[TestClass]
public class MyTestClass {
    [TestMethod]
    public async Task Test() {
        //Arrange
        var serviceMock = new Mock<IService>();
        var systemUnderTest = new Provider(serviceMock.Object) {
            HasResults = false
        };

        //Act
        serviceMock.Raise(mock => mock.OnResultsChanged += null, EventArgs.Empty);

        await Task.Delay(300); //<--wait

        //Assert
        Assert.IsTrue(systemUnderTest.HasResults);
    }
}