考虑以下 Blazor 组件:
@page "/"
<p id="message">@message</p>
@code {
string message = "Hello!";
public Task UpdateMessage(string newMessage)
{
message = newMessage;
StateHasChanged();
return Task.CompletedTask;
}
}
以及对上述代码进行单元测试的Bunit测试:
using Bunit;
namespace BlazorTest.Client.Tests
{
public class IndexTests : TestContext
{
[Fact]
public async Task MessageIsUpdated()
{
var component = RenderComponent<Pages.Index>();
Assert.Equal("Hello!", component.Find("#message").TextContent);
await component.Instance.UpdateMessage("Hello world!");
Assert.Equal("Hello world!", component.Find("#message").TextContent);
}
}
}
这会引发异常:
System.InvalidOperationException
The current thread is not associated with the Dispatcher. Use InvokeAsync() to switch execution to the Dispatcher when triggering rendering or component state.
请帮我解释一下这个错误的含义,以及如何修复它,以便我可以对功能进行单元测试?
[Fact]
public async Task MessageIsUpdated()
{
var component = RenderComponent<Pages.Index>();
Assert.Equal("Hello!", component.Find("#message").TextContent);
await component.InvokeAsync(() => component.Instance.UpdateMessage("Hello world!"));
Assert.Equal("Hello world!", component.Find("#message").TextContent);
}
首先,您的示例方法并不真正需要 StateHasChanged(),但对于这个问题来说这是可以的。
我不知道如何使用正确的同步上下文执行测试,但您可以调整您的代码:
public Task UpdateMessage(string newMessage)
{
message = newMessage;
return InvokeAsync(StateHasChanged);
//return Task.CompletedTask;
}
或者,更通用的异步和等待模式:
public async Task UpdateMessage(string newMessage)
{
message = newMessage;
await InvokeAsync(StateHasChanged);
}