bUnit: Test Runs Failing on net5.0
Describe the bug
Firstly this may not be a bug with bUnit. These are some observations and I would like some advice on how to log repro these issues. Since moving our library to net5.0 our test pipeline has started giving seemingly random failures. We almost exclusively do component testing using bUnit. I am really not sure where to start. Could it possibly be a timing bug with bUnit on Linux (the build server)? I am at a loss since it seems different test fail every time so finding a pattern is very hard as you can imagine. The below is just an example although it probably doesn’t help much sorry. This test will pass normally and will almost certainly pass if I just re-run the pipeline.
Example: Testing this component:
<MudButton Variant="Variant.Filled" OnClick="()=>visible=true">Open</MudButton>
<MudDialog @bind-IsVisible="visible">
<DialogContent>
<MudText>Wabalabadubdub!</MudText>
</DialogContent>
<DialogActions>
<MudButton Color="Color.Primary" OnClick="()=>visible=false">Close</MudButton>
</DialogActions>
</MudDialog>
@code {
public static string __description__ = "Click on open will open the inlined dialog";
bool visible;
}
With this test:
[TestFixture]
public class DialogTests
{
private Bunit.TestContext ctx;
[SetUp]
public void Setup()
{
ctx = new Bunit.TestContext();
ctx.AddTestServices();
}
[TearDown]
public void TearDown() => ctx.Dispose();
/// <summary>
/// Click outside the dialog (or any other method) must update the IsVisible parameter two-way binding on close
/// </summary>
/// <returns></returns>
[Test]
public async Task InlineDialog_Should_UpdateIsVisibleOnClose()
{
var comp = ctx.RenderComponent<MudDialogProvider>();
comp.Markup.Trim().Should().BeEmpty();
var service = ctx.Services.GetService<IDialogService>() as DialogService;
service.Should().NotBe(null);
// displaying the component with the inline dialog only renders the open button
var comp1 = ctx.RenderComponent<InlineDialogIsVisibleStateTest>();
// open the dialog
comp1.Find("button").Click();
Console.WriteLine("\nOpened dialog: " + comp.Markup);
comp.Find("div.mud-dialog-container").Should().NotBe(null);
// close by click outside
comp.Find("div.mud-overlay").Click();
comp.Markup.Trim().Should().BeEmpty();
// open again
comp1.Find("button").Click();
comp.Find("div.mud-dialog-container").Should().NotBe(null);
// close again by click outside
comp.Find("div.mud-overlay").Click();
comp.Markup.Trim().Should().BeEmpty();
}
}
public static class TestContextExtensions
{
public static void AddTestServices(this Bunit.TestContext ctx)
{
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
ctx.Services.AddSingleton<NavigationManager>(new MockNavigationManager());
ctx.Services.AddMudServices(options =>
{
options.SnackbarConfiguration.ShowTransitionDuration = 0;
options.SnackbarConfiguration.HideTransitionDuration = 0;
});
ctx.Services.AddScoped(sp => new HttpClient());
ctx.Services.AddOptions();
}
}
Results in this output:
Failed InlineDialog_Should_UpdateIsVisibleOnClose [25 ms]
Error Message:
Bunit.ElementNotFoundException : No elements were found that matches the selector 'div.mud-dialog-container'
Stack Trace:
at Bunit.RenderedFragmentExtensions.Find(IRenderedFragment renderedFragment, String cssSelector) in /_/src/bunit.web/Extensions/RenderedFragmentExtensions.cs:line 30
at MudBlazor.UnitTests.DialogTests.InlineDialog_Should_UpdateIsVisibleOnClose() in /home/vsts/work/1/s/src/MudBlazor.UnitTests/Components/DialogTests.cs:line 123
at NUnit.Framework.Internal.TaskAwaitAdapter.GenericAdapter`1.GetResult()
at NUnit.Framework.Internal.AsyncToSyncAdapter.Await(Func`1 invoke)
at NUnit.Framework.Internal.Commands.TestMethodCommand.RunTestMethod(TestExecutionContext context)
at NUnit.Framework.Internal.Commands.TestMethodCommand.Execute(TestExecutionContext context)
at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.<>c__DisplayClass1_0.<Execute>b__0()
NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.RunTestMethodInThreadAbortSafeZone(TestExecutionContext context, Action action)
Standard Output Messages:
Opened dialog: <div class="mud-dialog-container mud-dialog-center"><div class="mud-overlay mud-overlay-dialog" style="" blazor:onclick="2" blazor:onclick:stopPropagation><div class="mud-overlay-scrim mud-overlay-dark mud-overlay-dialog"></div>
<div class="mud-overlay-content"></div></div>
<div id="_9e7cbd63e65248b7b09ec03ebe80ff58" class="mud-dialog mud-dialog-width-sm"><div class="mud-dialog-title"><h6 class="mud-typography mud-typography-h6 mud-inherit-text"><svg class="mud-icon-root mud-svg-icon mud-inherit-text mud-icon-size-medium mr-3" focusable="false" viewBox="0 0 24 24" aria-hidden="true"><path d="M0 0h24v24H0z" fill="none"/><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg> Edit rating
</h6></div><div style="outline-style: none;" blazor:onkeydown="3" blazor:onkeyup="4" blazor:onfocus="5" tabindex="-1" blazor:elementReference=""><div style="pointer-events:none; position:fixed;" tabindex="0" blazor:onfocus="6"></div>
<div style="pointer-events:none; position:fixed;" tabindex="0" blazor:onfocus="7" blazor:elementReference=""></div>
<div style="pointer-events:none; position:fixed;" tabindex="-1" blazor:elementReference=""></div>
<div class="mud-dialog-content"><p>Close and re-open me by clicking out of the dialog. </p></div><div class="mud-dialog-actions"></div>
<div style="pointer-events:none; position:fixed;" tabindex="0" blazor:onfocus="8" blazor:elementReference=""></div>
<div style="pointer-events:none; position:fixed;" tabindex="0" blazor:onfocus="9"></div></div></div></div>
Expected behavior: Passes (It does usually)
Version info:
- bUnit version: preview 01
- .NET Runtime and Blazor version: 5.0.3
- OS type and version: buiild server Ubuntu 20.04.2
Additional context: Passes nearly all of the time. This is just one of seeming random failures. All tests that have passed in the past many times. One Thing that has chnaged that seems to have triggered these random failures is our library moving to net 5.0
cc @henon
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 28 (12 by maintainers)
No, this should ideally show up no matter what in the test output. It is the plan to fix that in #319.
Exactly.
Thanks for taking the time to report this. I am aware of the issue, and will be attempting to fix it in the next release.
I had another seemingly random failure but it was this. We render all our docs examples to check for errors. We don’t test any assertions. We mock api for http content retrieval using a MockHttpHandler, Every now and then I got an exception . I didn’t know why. But when I tested the MockHttpHandler directly it failed every time. I had an incorrect content type. Why does the thread not synchronise with the await call and bubble the exception back to the test thread?
This is the example
And the test which is auto generated just makes sure the example renders without error
Yes I will close. When I have another seemingly random failure I will do my best to tie it down. Certainly there is something going on on the build server that is not happening locally. Whether it be through poorly written tests or some complex threading issues I am not sure.
Thanks for clarifying @mikes-gh.
As for the WaitFor methods… you might need to use them when you have async operations that trigger the renders in the component, otherwise you are likely to see this issue that randomly shows up. That is expected, because the test code runs in its own thread, and the renderer runs in another. And if you trigger something from the test thread, e.g. by clicking a button, that causes the renderer to schedule a async render, e.g. due to a
Task.Delay
call, then you most definently need to use one of the WaitFor methods.You can read more about it here https://bunit.egilhansen.com/docs/interaction/awaiting-async-state.html and here https://bunit.egilhansen.com/docs/verification/async-assertion.html