Blazor WebAssembly集成测试中JSCallInfo类型加载失败原因排查
问题根源
你遇到的Could not load type 'WebAssembly.JSInterop.JSCallInfo'异常,核心原因是**WebApplicationFactory<T>是专门为服务器端ASP.NET Core应用(如Blazor Server、MVC)设计的测试工具**,它无法托管Blazor WebAssembly客户端应用:
- Blazor WASM运行在浏览器的WebAssembly环境中,依赖JavaScript运行时提供的JSInterop能力;
- 测试项目运行在桌面.NET环境下,没有WASM所需的JS运行时支撑,因此无法加载
Microsoft.JSInterop.WebAssembly中的相关类型。
解决方案
根据你的测试场景(用WireMock模拟API),分两种情况给出适配的测试方案:
方案1:测试客户端API调用逻辑(无需渲染Blazor组件)
直接创建指向WireMock服务器的HttpClient,跳过WebApplicationFactory的错误用法:
using WireMock.Server; using Xunit; using System.Net.Http.Json; public class ContactApiTests : IDisposable { private readonly WireMockServer _mockServer; private readonly HttpClient _httpClient; public ContactApiTests() { // 启动WireMock模拟服务器 _mockServer = WireMockServer.Start(); // 初始化指向Mock服务器的HttpClient _httpClient = new HttpClient { BaseAddress = new Uri(_mockServer.Urls[0]) }; } [Fact] public async Task GetContacts_WhenGetAll_ReturnsAllContacts() { // 配置WireMock返回模拟数据 _mockServer.Given(Request.Create().WithPath("/api/contacts").UsingGet()) .RespondWith(Response.Create() .WithStatusCode(200) .WithBodyAsJson(new List<Contact> { new Contact { Id = 1, Name = "Riley Christian" }, new Contact { Id = 2, Name = "Test User" } })); // 调用API(可直接复用你客户端项目中的服务类,注入此HttpClient) var response = await _httpClient.GetAsync("/api/contacts"); response.EnsureSuccessStatusCode(); var contacts = await response.Content.ReadFromJsonAsync<List<Contact>>(); // 断言结果符合预期 Assert.Equal(2, contacts?.Count); Assert.Contains(contacts, c => c.Name == "Riley Christian"); } // 清理资源 public void Dispose() { _mockServer.Stop(); _mockServer.Dispose(); _httpClient.Dispose(); } } // 假设你的Contact模型类 public class Contact { public int Id { get; set; } public string Name { get; set; } = string.Empty; }
方案2:测试Blazor组件与API的交互(含组件渲染)
如果需要测试组件调用API后的渲染逻辑,使用bUnit(Blazor专属测试库),它能模拟Blazor组件的渲染环境,无需启动完整WASM宿主:
首先安装Nuget包:Install-Package bunit
然后编写测试代码:
using Bunit; using WireMock.Server; using Xunit; public class ContactListComponentTests : IDisposable { private readonly WireMockServer _mockServer; private readonly TestContext _testContext; public ContactListComponentTests() { _mockServer = WireMockServer.Start(); _testContext = new TestContext(); // 替换组件依赖的HttpClient为指向WireMock的实例 _testContext.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(_mockServer.Urls[0]) }); } [Fact] public void ContactList_WhenLoaded_DisplaysMockedContacts() { // 配置WireMock响应 _mockServer.Given(Request.Create().WithPath("/api/contacts").UsingGet()) .RespondWith(Response.Create() .WithStatusCode(200) .WithBodyAsJson(new List<Contact> { new Contact { Id = 1, Name = "Alice" }, new Contact { Id = 2, Name = "Bob" } })); // 渲染目标组件 var component = _testContext.RenderComponent<ContactList>(); // 等待组件异步加载数据完成 component.WaitForState(() => component.FindAll(".contact-item").Count == 2); // 断言组件渲染内容正确 Assert.Contains("Alice", component.Markup); Assert.Contains("Bob", component.Markup); } public void Dispose() { _mockServer.Stop(); _mockServer.Dispose(); _testContext.Dispose(); } }
关键注意事项
- 永远不要用
WebApplicationFactory<T>托管Blazor WASM的Program类,它不具备WASM运行时环境; - 测试Blazor WASM的客户端逻辑,优先使用bUnit;测试API交互逻辑,直接对接WireMock+HttpClient即可。
内容的提问来源于stack exchange,提问作者Riley Christian
相关产品推荐
相关产品推荐

