bUnit - why does service.SetResult() cause a render change?

54 views Asked by At

The following test (from a PluralSight course) works:

[Fact]
public void AsyncAwait_Parameter_IndexComponent_Test()
{
    //Arrage
    string expectedStringValue = "Welcome to Blazor Unit Testing with bUnit";
    using var ctx = new TestContext();
    var textService = new TaskCompletionSource<string>();
    var rC = ctx.RenderComponent<Pages.Index>(p => p
    .Add(ts => ts.TextService, textService.Task));

    //Act
    textService.SetResult(expectedStringValue);
    rC.WaitForState(() => rC.Find("h6").TextContent == expectedStringValue);

    //Assert
    Assert.Contains(@"<h6>"+ expectedStringValue + "</h6>", rC.Markup);
}

My question is how does this work? The textService.SetResult(expectedStringValue) will cause the page property TextService task to be "completed". Does razor page rendering watch all properties that are a Task and trigger a re-render when a Task property completes?

Or is there something bUnit specific going on?

2

There are 2 answers

2
MrC aka Shaun Curtis On BEST ANSWER

The code block you've provided, which obviously comes from the PluralSight course, comes almost ad verbatim from the BUnit documentation which you can find here: https://bunit.dev/docs/interaction/awaiting-async-state.html#waiting-for-state-using-waitforstate.

I'll quote [almost verbatim] from Egil Hansens's BUnit document:

This is what happens in the test:

  1. The test uses a TaskCompletionSource<string> to simulate an async web service.

  2. The result is provided to the component through the textService. This causes the component to re-render. BUnit emulating the renderer, detects a Parameter change and calls SetParametersAsync on the component.

  3. The WaitForState() method is used to block the test until the predicate provided to it returns true.

  4. Finally, the test's assertion step can execute, knowing that the desired state has been reached.

0
Henk Holterman On

TaskCompletionSource represents a future result and gives an ability to set the final state of the underlying task manually by calling SetCanceled, SetException or SetResult methods.

So yes, it sets the task to completed. And then OnInitializedAsync (I assume the Index page has one) continues executing and when that's finished the system (bUnit here) will render the component.

Post the Index.razor code if you need a more detailed answer.