You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用bUnit编写MudBlazor单元测试遇MudPopover渲染空引用错误

问题

尝试用bUnit编写单元测试时,渲染组件因MudPopover报错失败,错误信息如下:

System.NullReferenceException
  HResult=0x80004003
  Message=Object reference not set to an instance of an object.
  Source=MudBlazor
  StackTrace:
   at MudBlazor.MudPopover.BuildRenderTree(RenderTreeBuilder __builder)
   at Microsoft.AspNetCore.Components.ComponentBase.<.ctor>b__6_0(RenderTreeBuilder builder)
   at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, Exception& renderFragmentException)
--- End of stack trace from previous location ---
   at Bunit.Rendering.TestRenderer.AssertNoUnhandledExceptions()
   at Bunit.Rendering.TestRenderer.Render[TResult](RenderFragment renderFragment, Func`2 activator)
   at Bunit.Rendering.TestRenderer.RenderFragment(RenderFragment renderFragment)
   at Bunit.Extensions.TestContextBaseRenderExtensions.RenderInsideRenderTree(TestContextBase testContext, RenderFragment renderFragment)
   at Bunit.Extensions.TestContextBaseRenderExtensions.RenderInsideRenderTree[TComponent](TestContextBase testContext, RenderFragment renderFragment)
   at Bunit.TestContext.Render[TComponent](RenderFragment renderFragment)
   at Bunit.TestContext.RenderComponent[TComponent](Action`1 parameterBuilder)

随后尝试直接加载组件排查逻辑(代码如下),仍出现相同错误,求bUnit测试中Mock或初始化MudPopover的正确方法:

[Fact]
public void TestRender()
{
    var services = new ServiceCollection();
    using var context = new TestContext();
    services.AddMudServices();
    services.AddSingleton<MudPopoverProvider>();
    var mudPop = new Mock<MudPopover>();
    var mudPoperProvider = new Mock<MudPopoverProvider>();
    var mudPopService = new Mock<IMudPopoverService>();

    mudPop.Setup(m => m.SetParametersAsync(new ParameterView())).Returns(Task.CompletedTask);
    context.Services.AddSingleton(mudPoperProvider.Object);
    context.Services.AddSingleton(mudPop.Object);
    context.Services.AddSingleton(mudPopService.Object);


    context.RenderComponent<MudPopoverProvider>();
    context.RenderComponent<MudPopover>();
}
解决方案

核心问题

当前Mock方式存在两处错误:

  • MudPopover是Blazor组件而非服务,不能通过依赖注入注入Mock实例;
  • 手动创建的ServiceCollection未关联到TestContext,导致AddMudServices()的配置未生效。

正确实现步骤

  1. 正确注册MudBlazor服务
    无需单独创建ServiceCollection,直接在TestContext上配置MudBlazor服务即可,AddMudServices()已包含IMudPopoverService、MudPopoverProvider等必要服务的正确注册:

    using var context = new TestContext();
    context.Services.AddMudServices();
    
  2. 避免直接渲染MudPopover
    MudPopover是MudBlazor的内部组件,依赖父组件传递的上下文参数(如PopoverId、Placement),单独渲染必然触发空引用异常。测试应聚焦于使用MudPopover的自定义组件,直接渲染该自定义组件即可。

  3. 按需Mock IMudPopoverService
    如果需要自定义弹出逻辑,可覆盖TestContext中的IMudPopoverService实例:

    var mockPopoverService = new Mock<IMudPopoverService>();
    // 模拟弹出方法返回有效ID
    mockPopoverService.Setup(s => s.Show(It.IsAny<MudPopoverOptions>())).Returns(Guid.NewGuid());
    // 替换TestContext中的服务
    context.Services.AddSingleton(mockPopoverService.Object);
    
  4. 完整测试示例
    假设测试目标是包含MudPopover的自定义组件MyPopoverComponent:

    [Fact]
    public void TestCustomComponentWithMudPopover()
    {
        using var context = new TestContext();
        // 注册MudBlazor服务
        context.Services.AddMudServices();
        
        // 可选:Mock弹出服务行为
        var mockPopoverService = new Mock<IMudPopoverService>();
        mockPopoverService.Setup(s => s.Show(It.IsAny<MudPopoverOptions>())).Returns(Guid.NewGuid());
        context.Services.AddSingleton(mockPopoverService.Object);
        
        // 渲染自定义组件
        var cut = context.RenderComponent<MyPopoverComponent>();
        
        // 触发弹出动作并验证服务调用
        cut.Find(".popover-trigger-btn").Click();
        mockPopoverService.Verify(s => s.Show(It.IsAny<MudPopoverOptions>()), Times.Once);
    }
    

关键注意事项

  • 无需测试MudPopover本身,这类组件的正确性由MudBlazor官方测试保障,你的测试应聚焦于自身业务组件的逻辑。
  • AddMudServices()已自动处理MudPopoverProvider的初始化,无需手动注册或渲染该组件。

内容的提问来源于stack exchange,提问作者ist_lion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 02:05:43