I have a Blazor component that performs multiple validations on an uploaded file. If both validations fail, it should show two separate alerts. In my bUnit test, I mock both validations to fail, yet Assert.Equal(1, alerts.Count()) passes, even though I expect it to find 2 and fail.
It appears WaitForAssertion resolves as soon as the first error renders, rather than waiting for the logic to finish.
The Logic (Code Behind):
private void AddFilesToQueue(InputFileChangeEventArgs e)
{
try
{
var files = e.GetMultipleFiles();
foreach (var file in files)
{
if (!fileValidator.IsSizeValid(file.Size, ...)) {
filesOverMaxSize.Add(file);
}
if (!fileValidator.IsTypeValid(file.Name, ...)) {
filesWrongType.Add(file);
}
}
if (filesOverMaxSize.Count > 0)
{
foreach (var file in filesOverMaxSize)
FileSizeErrors?.Add($"Size error for {file.Name}");
}
if (filesWrongType.Count > 0)
{
foreach (var file in filesWrongType)
FileTypeErrors?.Add($"Type error for {file.Name}");
}
StateHasChanged();
}
catch (InvalidOperationException ex) { ErrorMessage = ex.Message; }
}
The Markup:
@if (!string.IsNullOrEmpty(ErrorMessage))
{
@ErrorMessage
}
@foreach (string message in FileSizeErrors ?? new())
{
@message
}
@foreach (string message in FileTypeErrors ?? new())
{
@message
}
The Test:
[Fact]
public void SingleErrorShown_WhenSingleFileHasMultipleFailures()
{
AddInjectedServices();
var serviceMock = new Mock>();
serviceMock.SetupProperty(m => m.FilingSettings, new FilingSettingsClient());
// Mock BOTH to fail
serviceMock.Setup(m => m.IsSizeValid(It.IsAny(), It.IsAny())).Returns(false);
serviceMock.Setup(m => m.IsTypeValid(It.IsAny(), It.IsAny())).Returns(false);
Services.AddSingleton(serviceMock.Object);
var component = Render();
var fileToUpload = InputFileContent.CreateFromBinary(new byte[100], "invalid-type.exe");
// Act
component.FindComponent().UploadFiles(fileToUpload);
// Assert - This SHOULD fail because 2 alerts should exist, but it PASSES.
component.WaitForAssertion(() =>
{
var alerts = component.FindAll(".alert");
Assert.Equal(1, alerts.Count());
}, TimeSpan.FromSeconds(3));
serviceMock.Verify(m => m.IsTypeValid(It.IsAny(), It.IsAny()), Times.AtLeastOnce());
}
Observations:
Verifyconfirms both validation methods are called.If I change the assertion to
Assert.Equal(2, alerts.Count()), the test also passes, proving the second alert eventually appears.It seems
WaitForAssertionexits as soon as the firstifblock triggers a render, ignoring the subsequent state changes.
How do I ensure bUnit waits for the final render state before completing the assertion?