异步事件侦听器的 Moq Raise

Tul*_*ara 5 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;)
       }
   }
Run Code Online (Sandbox Code Playgroud)

为简化起见,我已将 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);
}
Run Code Online (Sandbox Code Playgroud)

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

谢谢!

Nko*_*osi 5

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

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

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; }
}
Run Code Online (Sandbox Code Playgroud)

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

[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);
    }
}
Run Code Online (Sandbox Code Playgroud)