如何使用bUnit测试通过JSRuntime与JS交互的Blazor组件?
Blazor组件bUnit测试:JS回调触发.NET事件的解决方案
问题背景
我有一个Blazor组件,通过JSRuntime与JavaScript交互,借助dotNetObjectRef实现JS到.NET的回调逻辑:
- .NET端调用JS的
addEventListener方法完成配置 - JS端通过
dotNetObjectRef.invokeMethodAsync("handler")触发组件的OnInit事件
组件运行正常,但使用bUnit测试时,JS代码完全无法执行,导致测试断言失败。现有测试代码如下:
[Fact] public async Task Events_ThatEventIsRaised() { bool isEventRaised = false; // Arrange using var context = CreateContext(); // Act var myComponent = context.RenderComponent<MyComponent>(parameters => parameters .Add(p => p.OnInit, e => isEventRaised = true) ); // Assert Assert.True(isEventRaised); }
我曾尝试手动加载JS文件context.JSInterop.SetupModule("component.js"),但并未生效。
解决方案
bUnit不会执行真实的JavaScript代码,因此需要模拟JS对dotNetObjectRef的调用逻辑,而不是加载真实JS文件。具体步骤如下:
- 拦截组件调用的JS方法
addEventListener,捕获传入的DotNetObjectReference实例 - 手动调用该实例的
InvokeAsync方法,模拟JS端触发.NET回调的行为
修改后的测试代码:
[Fact] public async Task Events_ThatEventIsRaised() { bool isEventRaised = false; using var context = CreateContext(); // 拦截JS的addEventListener调用,保存组件传入的DotNetObjectReference IDotNetObjectReference? dotNetRef = null; context.JSInterop.SetupVoid("addEventListener", _ => true) .SetVoidResult() .Callback((_, objRef) => dotNetRef = objRef as IDotNetObjectReference); // 渲染组件,此时组件会调用JS方法,dotNetRef被赋值 var myComponent = context.RenderComponent<MyComponent>(parameters => parameters .Add(p => p.OnInit, e => isEventRaised = true)); // 模拟JS端调用handler方法,触发.NET的OnInit事件 if (dotNetRef != null) { await dotNetRef.InvokeAsync<string>("handler"); } // 断言事件已被正确触发 Assert.True(isEventRaised); }
关键说明
- bUnit的
JSInterop是模拟层,仅用于拦截.NET对JS的调用,不会执行真实JS代码 - 通过
Callback捕获DotNetObjectReference,这是JS与.NET回调通信的核心对象 - 手动调用
InvokeAsync模拟JS端的触发逻辑,确保.NET组件的事件处理逻辑被执行
内容的提问来源于stack exchange,提问作者abberdeen
相关产品推荐
相关产品推荐

