Reputation: 1416
I'm new to Blazor and bUnit. I have component that renders an edit form and I get the values for the form in my OnInitializedAsync event.
I'm having trouble working out how to use cut.WaitForState() or cut.WaitForAssertion().
Here's my razor code:
@page "/{AppId:guid}/app-settings-edit"
<section class="app-settings-edit">
<h1 class="page-title">Application Settings</h1>
@if (InitializedComplete)
{
<p>Hello World</p>
...
And my code behind:
public partial class AppSettingsEdit
{
protected bool InitializedComplete;
[Parameter]
public Guid AppId { get; set; }
[ValidateComplexType]
public AppSettings AppSettings { get; set; } = new AppSettings();
[Inject]
public IAppSettingsDataService AppSettingsDataService { get; set; }
protected override async Task OnInitializedAsync()
{
AppSettings = await AppSettingsDataService.Get(AppId);
InitializedComplete = true;
}
...
And here's my Test:
[Fact]
public void MyFact()
{
Services.AddSingleton<IAppSettingsDataService, MockAppSettingsDataService>(x => new MockAppSettingsDataService(x.GetRequiredService<HttpClient>()));
var cut = RenderComponent<AppSettingsEdit>(parameters => parameters
.Add(p => p.AppId, Guid.Parse("55E5097B-B56A-40D7-8A02-A5B94AAAD6E1"))
);
Assert.NotNull(cut.Instance.AppSettingsDataService);
cut.WaitForState(() => cut.Find("p").TextContent == "Hello World", new TimeSpan(0, 0, 5));
cut.MarkupMatches("<p>Hello World</p>");
}
When I debug the test, I can see the OnInitializedAsync firing, however my markup never changes to include 'Hello World' and the WaitForState() command fails.
Upvotes: 1
Views: 624
Reputation: 1
I'm having the same issue, except my app is server-side. However, the component in question is in a library. In arrange, I created the customer object with Field = "";
var cut = ctx.RenderComponent<MyComponent>(parameters => parameters
.Add(p => p.Customer, customer)
);
// Act
var isValid = cut.Instance.Validate();
// Assert
Assert.False(isValid);
// now wait for test warning to show up
cut.WaitForAssertion(() => Assert.NotNull(cut.Find("p#empty-warning")));
And in my component:
@if (IsSaving && string.IsNullOrWhiteSpace(Field))
{
<p id="empty-warning" style="color: red;">Field is required.</p>
}
In the //Act step, I call Validate which sets IsSaving = true; and the Field is still "".
When I run my app, obviously the change in IsSaving prompts the if to be reevaluated and then the re-render occurs. I'm not sure how else to get it to happen in bunit, the re-evaluation and re-render. Does anyone see what is wrong in my case?
Upvotes: 0
Reputation: 15598
Are you certain that the task returned from your AppSettingsDataService.Get()
method ever completes?
I would make sure that the task returned from AppSettingsDataService.Get()
is already completed, otherwise you need to a way to complete the task after the component is rendered. There are many ways to do this, it all depends on how your mock is implemented.
As for your WaitFor
, you can just use the WaitForAssertion
method in this case, i.e.: cut.WaitForAssertion(() => cut.MarkupMatches("<p>Hello World</p>"));
A little background:
The WaitFor*
methods are used when the component under test is being rendered asynchronously, since the test, running in a different thread, doesn't know when that will happen.
In general, you should never need to set a custom timeout, the default is 1 second, but the WaitFor*
methods will retry the assertion/predicate every time a renderer happens. Its only when the thing that triggers the rendering will take more than one second, e.g. if you are using bUnit to perform end-2-end testing and e.g. pulling data from a real web service.
Upvotes: 1