如何用Moq模拟Blazor EventCallback并验证其触发?
Blazor组件bUnit测试的Moq使用与事件验证问题
问题1:能否用Moq替代自定义Handler并传递给组件?
可以,但需要注意EventCallback<string>的委托签名适配问题,以下是两种可行方案:
方案一:直接Mock适配EventCallback的委托类型
EventCallback<string>接受Action<string>或Func<string, Task>类型的委托,直接MockAction<string>更贴合需求:
// 创建Action<string>的Mock var mockHandler = new Mock<Action<string>>(); // 设置预期:接受任意字符串参数 mockHandler.Setup(h => h(It.IsAny<string>())).Verifiable(); // 渲染组件时传递Mock的委托 var cut = RenderComponent<MyComp>(builder => { builder.Add(mc => mc.OnEvent, EventCallback.Factory.Create<string>(this, mockHandler.Object)); }); // 触发组件事件 await cut.Instance.OnEvent.InvokeAsync("Fired");
方案二:适配EventHandler到EventCallback
如果坚持使用EventHandler<string>,需要将Mock的Handler包装成符合EventCallback要求的委托:
// 定义泛型事件参数类(若项目中没有的话) public class EventArgs<T> : EventArgs { public T Value { get; } public EventArgs(T value) => Value = value; } // 创建EventHandler<string>的Mock var mockHandler = new Mock<EventHandler<string>>(); mockHandler.Setup(h => h(It.IsAny<object>(), It.IsAny<EventArgs<string>>())).Verifiable(); // 包装成Action<string>适配EventCallback Action<string> wrappedHandler = val => mockHandler.Object.Invoke(this, new EventArgs<string>(val)); var cut = RenderComponent<MyComp>(builder => { builder.Add(mc => mc.OnEvent, EventCallback.Factory.Create<string>(this, wrappedHandler)); }); await cut.Instance.OnEvent.InvokeAsync("Fired");
问题2:如何验证OnEvent已被触发?
用Moq的Verify方法验证
如果使用了Moq的Mock对象,直接调用Verify方法即可验证事件触发情况:
// 验证委托被调用过1次,参数为"Fired" mockHandler.Verify(h => h("Fired"), Times.Once); // 或者验证接受任意字符串参数且被调用过1次 mockHandler.Verify(h => h(It.IsAny<string>()), Times.Once);
自定义标记验证(无需Moq)
如果不想依赖Moq,可以通过标记变量记录事件触发状态:
bool eventWasTriggered = false; string receivedEventValue = null; var cut = RenderComponent<MyComp>(builder => { builder.Add(mc => mc.OnEvent, val => { eventWasTriggered = true; receivedEventValue = val; }); }); await cut.Instance.OnEvent.InvokeAsync("Fired"); // 断言验证 Assert.True(eventWasTriggered); Assert.Equal("Fired", receivedEventValue);
内容的提问来源于stack exchange,提问作者phil
相关产品推荐
相关产品推荐

