我们如何在 Blazor Bunit 单元测试中调用调用 StateHasChanged 的方法

问题描述 投票:0回答:2

考虑以下 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.

请帮我解释一下这个错误的含义,以及如何修复它,以便我可以对功能进行单元测试?

async-await blazor bunit
2个回答
3
投票
[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);
}

1
投票

首先,您的示例方法并不真正需要 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);
}
© www.soinside.com 2019 - 2024. All rights reserved.