Skip to content

1.0.0 - preview 02 - final release before v1

Compare
Choose a tag to compare
@egil egil released this 26 Mar 16:18
· 1337 commits to main since this release

[1.0.0-preview-02] - 2021-03-26

The following sections list all changes in 1.0.0 preview 02.

The plan is to make this the last preview release of bUnit. If no big blocking bugs show up the next two weeks, a non-preview release of bUnit will be pushed out to the world.

Added

List of new features.

  • Added the ability to pass a "fallback IServiceProvider" to the TestServiceProvider, available through the Services property on a TestContext. The fallback service provider enables a few interesting scenarios, such as using an alternative IoC container, or automatically generating mocks of services components under test depend on. See the Injecting Services into Components Under Test page for more details on this feature. By @thopdev in #310.

  • Added Task<Expection> ITestRenderer.UnhandledException property that returns a Task<Exception> that completes when the renderer captures an unhandled exception from a component under test. If a component is missing exception handling of asynchronous operations, e.g. in the OnInitializedAsync method, the exception will not break the test, because it happens on another thread. To have a test fail in this scenario, you can await the UnhandledException property on the TestContext.Renderer property, e.g.:

    using var ctx = new TestContext();
    
    var cut = ctx.RenderComponent<ComponentThatThrowsDuringAsyncOperation>();
    
    Task<Exception?> waitTimeout = Task.Delay(500).ContinueWith(_ => Task.FromResult<Exception?>(null)).Unwrap();
    Exception? unhandledException = await Task.WhenAny<Exception?>(Renderer.UnhandledException, waitTimeout).Unwrap();
    
    Assert.Null(unhandledException);

    In this example, we await any unhandled exceptions from the renderer, or our wait timeout. The waitTimeout ensures that we will not wait forever, in case no unhandled exception is thrown.

    NOTE, a better approach is to use the WaitForState or WaitForAssertion methods, which now also throws unhandled exceptions. Using them, you do not need to set up a wait timeout explicitly.

    By @egil in #344.

  • Added a simple fake navigation manager, which is registered by default in bUnit's service provider. When the fake navigation manager's NavigateTo method is called, it does two things:

    1. Set the Uri property to the URI passed to the NavigateTo method (with the URI normalized to an absolute URI).
    2. Raise the LocationChanged event with the URI passed to the NavigateTo method.

    Lets look at an example: To verify that the <GoesToFooOnInit> component below calls the NavigationManager.NavigateTo method with the expected value, do the following:

    <GoesToFooOnInit> component:

    @inject NavigationManager NavMan
    @code {
      protected override void OnInitialized()
      {
        NavMan.NavigateTo("foo");
      }
    }

    Test code:

    // Arrange
    using var ctx = new TestContext();
    var navMan = ctx.Services.GetRequiredService<NavigationManager>();
    
    // Act
    var cut = ctx.RenderComponent<GoesToFooOnInit>();
    
    // Assert
    Assert.Equal($"{navMan.BaseUri}foo", navMan.Uri);

    Since the foo input argument is normalized to an absolute URI, we have to do the same normalization in our assertion.

    The fake navigation manager's BaseUri is set to http://localhost/, but it is not recommended to use that URL directly in your code. Instead create an assertion by getting that value from the BaseUri property, like shown in the example above.

    By @egil in #345.

  • Added additional bUnit JSInterop Setup methods, that makes it possible to get complete control of invocation matching for the created handler. By @egil.

Changed

List of changes in existing functionality.

  • WaitForAssertion and WaitForState now throws unhandled exception caught by the renderer from a component under test. This can happen if a component is awaiting an asynchronous operation that throws, e.g. a API call using a misconfigured HttpClient. By @egil in #310.

  • Improvements to error message from bUnit's JSInterop when it receives an invocation that it has not been set up to handle. By @egil in #346.