bUnit bUnit
Search Results for

    Show / Hide Table of Contents

    Triggering a Render Life Cycle on a Component

    When a component under test is rendered, an instance of the IRenderedComponent<TComponent> type is returned. Through that, it is possible to cause the component under test to render again directly through the Render() method or one of the SetParametersAndRender() methods, or indirectly through the InvokeAsync() method.

    Warning

    The Render() and SetParametersAndRender() methods are not available in the IRenderedFragment type that is returned when calling the non-generic version of GetComponentUnderTest() in <Fixture>-based Razor tests. Call the generic version of GetComponentUnderTest<TComponent>() to get a IRenderedComponent<TComponent>.

    Note

    These methods are available and work the same way in both C#- and Razor-based tests. The examples below are from C#-based tests only.

    Let's look at how to use each of these methods to cause a re-render.

    Render

    The Render() method tells the renderer to re-render the component, i.e. go through its life-cycle methods (except for OnInitialized() and OnInitializedAsync() methods). To use it, do the following:

    using var ctx = new TestContext();
    var cut = ctx.RenderComponent<Heading>();
    Assert.Equal(1, cut.RenderCount);
    
    // Re-render without new parameters
    cut.Render();
    
    Assert.Equal(2, cut.RenderCount);
    

    The highlighted line shows the call to Render().

    Tip

    The number of renders a component has been through can be inspected and verified using the RenderCount property.

    SetParametersAndRender

    The SetParametersAndRender(...) methods tells the renderer to re-render the component with new parameters, i.e. go through its life-cycle methods (except for OnInitialized() and OnInitializedAsync() methods), passing the new parameters — but only the new parameters — to the SetParametersAsync() method. To use it, do the following:

    using var ctx = new TestContext();
    var cut = ctx.RenderComponent<Item>(parameters => parameters
      .Add(p => p.Value, "Foo")
    );
    cut.MarkupMatches("<span>Foo</span>");
    
    // Re-render with new parameters
    cut.SetParametersAndRender(parameters => parameters
      .Add(p => p.Value, "Bar")
    );
    
    cut.MarkupMatches("<span>Bar</span>");
    

    The highlighted line shows the call to SetParametersAndRender(), which is also available as a version that takes the zero or more component parameters, e.g. created through the component parameter factory helper methods, if you prefer that method of passing parameters.

    Note

    Passing parameters to components through the SetParametersAndRender(...) methods is identical to doing it with the RenderComponent<TComponent>(...) methods, described in detail on the Passing Parameters to Components page.

    InvokeAsync

    Invoking methods on a component under test, which causes a render, e.g. by calling StateHasChanged, can result in the following error, if the caller is running on another thread than the renderer's thread:

    The current thread is not associated with the Dispatcher. Use InvokeAsync() to switch execution to the Dispatcher when triggering rendering or component state.

    If you receive this error, you need to invoke your method inside an Action delegate passed to the InvokeAsync(...) method.

    Let’s look at an example of this, using the <Calc> component listed below:

    <output>@result</output>
    
    @code 
    {
      int result = 0;
    
      public void Calculate(int x, int y)
      {
        result = x + y;
        StateHasChanged();
      }
    }
    

    To invoke the Calculate() method on the component instance, do the following:

    using var ctx = new TestContext();
    var cut = ctx.RenderComponent<Calc>();
    
    // Indirectly re-renders through the call to StateHasChanged 
    // in the Calculate(x, y) method.
    cut.InvokeAsync(() => cut.Instance.Calculate(1, 2));
    
    cut.MarkupMatches("<output>3</output>");
    

    The highlighted line shows the call to InvokeAsync(...), which is passed an Action delegate that calls the Calculate method.

    Tip

    The instance of a component under test is available through the Instance property.

    Editorial support provided by Packt.

    • Improve this Doc
    Back to top Documentation updated on 2/26/2021 3:36:12 PM +00:00 in commit 95ed9179f0.