async-awaitblazorbunit

How do we invoke methods that call StateHasChanged in Blazor Bunit unit tests


Consider the following Blazor component:

@page "/"
<p id="message">@message</p>

@code {

    string message = "Hello!";

    public Task UpdateMessage(string newMessage)
    {
        message = newMessage;
        StateHasChanged();
        return Task.CompletedTask;
    }
}

And the Bunit test that unit tests the above code:

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);
        }
    }
}

This throws an exception saying:

 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.

Please could I have some help explaining what this error means, and how to fix it so that I can unit test the functionality?


Solution

  • [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);
    }