bUnit: Bunit.Rendering.UnknownEventHandlerIdException since 1.5.12

Describe the bug

Since I upgrade bunit from 1.4.15 to 1.5.12 I’ve a lot of Bunit.Rendering.UnknownEventHandlerIdException I don’t have with 1.4.15 on same test without any modification.

Example: Testing this component:

@page "/roles"
@inherits EntitiesModel<Entity.Role>

<div class="row sticky-top bg-light">
    <div class="col">
        <PageListHeader Name="@Localizer["Roles"]" Url="role" ExportRequest="@ExportRequest" ExportDisabled="@ExportDisabled" />
    </div>
    <div class="col">
        <Filter TermChanged="OnFilterChanged" />
    </div>
    <EntitiesGrid Items="EntityList" TableClass="table mb-0">
        <TableHeader>
            <th><SelectAll GridState="GridState" /></th>
            <th class="w-50" scope="col">
                <SortableHeader Property="Id"
                                Text="@Localizer["id"]"
                                GridState="GridState" />
            </th>
            <th class="w-50" scope="col">
                <SortableHeader Property="Name"
                                Text="@Localizer["name"]"
                                GridState="GridState" />
            </th>
        </TableHeader>
    </EntitiesGrid>
</div>
@if (EntityList == null)
{
    <Loading />
}
else
{
    <div class="row">
        <EntitiesGrid Items="EntityList" TableClass="table table-hover">
            <RowTemplate>
                <SelectableItem GridState="GridState" Item="@context" Selected="value => OnItemSelected(context.Id, value)" Context="item">
                    <td class="w-50" @onclick="() => OnRowClicked(item)">@item.Id</td>
                    <td class="w-50" @onclick="() => OnRowClicked(item)">@item.Name</td>
                </SelectableItem>
            </RowTemplate>
        </EntitiesGrid>
    </div>
}

With this test:

[Fact]
public async Task OnRowClicked_should_navigate_to_entity_page()
{
    await PopulateList();

    var component = CreateComponent("Alice Smith",
        SharedConstants.WRITERPOLICY);

    component.WaitForState(() => component.Markup.Contains("filtered"), TimeSpan.FromMinutes(1));

    var navigationManager = Services.GetRequiredService<NavigationManager>();

    var tdList = component.FindAll(".table-hover tr td");

    Assert.NotEmpty(tdList);

    await tdList[tdList.Count - 1].ClickAsync(new MouseEventArgs());

    Assert.Contains(typeof(TEntity).Name.ToLower(), navigationManager.Uri);
}

Results in this output:

Bunit.Rendering.UnknownEventHandlerIdException : There is no event handler with ID '12' associated with the 'onclick' event in the current render tree. This can happen, for example, when using cut.FindAll(), and calling event trigger methods on the found elements after a re-render of the render tree. The workaround is to use re-issue the cut.FindAll() after each render of a component, this ensures you have the latest version of the render tree and DOM tree available in your test code.
---- System.ArgumentException : There is no event handler associated with this event. EventId: '12'. (Parameter 'eventHandlerId')
at Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.<>c.<<InvokeAsync>b__9_0>d.MoveNext()
--- End of stack trace from previous location ---
   at Aguacongas.TheIdServer.IntegrationTest.BlazorApp.Pages.EntitiesPageTestBase`2.OnRowClicked_should_navigate_to_entity_page() in C:\projects\theidserver\test\Shared\Aguacongas.TheIdServer.IntegrationTest.Shared\BlazorApp\Pages\EntitiesPageTestBase.cs:line 114
--- End of stack trace from previous location ---
----- Inner Stack Trace -----
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetRequiredEventCallback(UInt64 eventHandlerId)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.DispatchEventAsync(UInt64 eventHandlerId, EventFieldInfo fieldInfo, EventArgs eventArgs)
   at Bunit.Rendering.TestRenderer.<>c__DisplayClass16_0.<DispatchEventAsync>b__0() in /_/src/bunit.core/Rendering/TestRenderer.cs:line 88

Expected behavior:

No excection

Version info:

  • bUnit version: 1.5.12
  • .NET Runtime and Blazor version: 6.0.2
  • OS type and version: Windows

Additional informations

That occurs only on the ‘onclick’ event using ClickAsync never with method TrigerEventAsync nor ChangeAsync nor SubmitAsync

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 15 (4 by maintainers)

Commits related to this issue

Most upvoted comments

I guess I found the issue. I’ll make a PR for that. @egil the issue is that in DispatchEventAsync we handle the Exception in Dispatcher.InvokeAsync but return Task.FromException. So the Task is officially in a faulted state… forever. But we don’t want this! We introduced with #605 cases where we say: “Hey it’s fine”. It only shows with await as awaiting a Task in a faulted state will lead to an exception. Omitting async or using the sync version Click will therefore succeed.

I hope that makes sense 😄 I can explain later a bit better.

Anyway I make a small PR: I just move the handling into the InvokeAsync and return a completed Task when we want to ignore the exception.

@aguacongas Sorry for the inconvenience on that one.

@linkdotnet Yes, it does.

@egil, @linkdotnet I do not reproduce with 1.6.2-preview

@egil thanks for the update, I’ll try asap

Hi @aguacongas

@linkdotnet was able to find the regression and there should be a fix landing in the nightly channel. If you can try it out against your test suite, that would be great, and if everything works as expected, I will push a new minor release as soon as possible.

See https://github.com/bUnit-dev/bUnit/discussions/209 for how to try the nightly builds.

@egil That does sound like an area where we changed some stuff. Most probable: this

I suspect that now exceptions are bubbling which didn’t bubble before for some reason. Can have a look into it @aguacongas By any chance do you have a reproducible and minimal example?

@egil No it’s not happen if I use Click

<div class="row sticky-top bg-light"><div class="col"><div class="row"><h3 class="col">Roles</h3>
    <div class="col"><a href="role" class="btn btn-sm btn-primary"><span class="oi oi-plus"></span> Add</a>
                <button class="btn btn-secondary btn-sm" blazor:onclick="7" disabled title="export"><span class="oi oi-arrow-circle-top"></span><span class="visually-hidden">export</span></button></div></div></div>
    <div class="col"><div class="input-group input-group-sm "><div class="input-group-prepend"><span class="input-group-text oi oi-magnifying-glass" id="addon"></span></div>
    <input class="form-control" type="text" placeholder="filter" aria-label="filter" aria-describedby="addon" blazor:oninput="1" blazor:onfocusout="2" blazor:onfocus="3" /></div></div>
    <table class="table mb-0"><thead class="select"><tr class="select"><th><input type="checkbox" blazor:onchange="8" /></th>
            <th class="w-50" scope="col"><div blazor:onclick="5">id
    <span class="oi oi-arrow- float-right sort"></span></div></th>
            <th class="w-50" scope="col"><div blazor:onclick="6">name
    <span class="oi oi-arrow- float-right sort"></span></div></th></tr></thead></table></div><div class="row"><table class="table table-hover"><tbody><div style="height: 0px;" blazor:elementReference=""></div><tr class="select" blazor:onclick="9"><td><input type="checkbox" blazor:onclick:stopPropagation blazor:onchange="10" /></td>
<td class="w-50" blazor:onclick="11">8cb7ec62-2a6c-46bd-9517-b127e60a8961</td>
                    <td class="w-50" blazor:onclick="12">filtered</td></tr><div style="height: 0px;" blazor:elementReference=""></div></tbody></table></div>