I am unit testing a blazor app. I get a ElementNotFoundException. I think the cause for this is an if statement in the the index.razor page. see code below:
<div class="row">
<div class="col-12">
@if ((challenges != null) && (challenges.Count > 0))
{
<MultiStepComponent Id="MultiStepContainer" Challenges="@challenges">
<div class="row p-3">
<div class="col-6" id="challengeContainer">
@foreach(var c in challenges)
{
<MultiStepNavigation Name="@c.Title">
<h1>@c.Title</h1>
<img class="float-left" src="@c.ImagePath" width="200" />
@foreach(var sentence in c.Description)
{
<p>@sentence</p>
}
</MultiStepNavigation>
}
</div>
<div class="col-6">
<textarea rows="26" cols="120" @bind="input" id="input"></textarea>
<button class="btn" id="runBtn" @onclick="RunAsync">Run</button>
<br />
<textarea rows="10" cols="120" id="output" readonly>@((MarkupString)Output)</textarea>
</div>
</div>
</MultiStepComponent>
}
</div>
</div>
The code behind of this page (index.razor.cs) has the following initialization code:
protected override async Task OnInitializedAsync()
{
jsonRepository = new JSONChallengeRepository();
challenges = await jsonRepository.GetChallengesAsync();
}
The test for this page is here:
[Test]
public async Task Compile_code_Success()
{
_codingChallengeService.Setup(c => c.SendInputToCompilerAsync("50+50")).ReturnsAsync("100");
_testContext.Services.AddScoped(x => _codingChallengeService.Object);
var razorComponent = _testContext.RenderComponent<Index>();
razorComponent.Instance.challenges = GetChallenges();
if ((razorComponent.Instance.challenges != null) && (razorComponent.Instance.challenges.Count > 0))
{
var runBtn = razorComponent.FindAll("button").FirstOrDefault(b => b.OuterHtml.Contains("Run"));
var input = razorComponent.Find("#input");
input.Change("50+50");
runBtn.Click();
var outputArea = razorComponent.Find("#output");
var outputAreaText = outputArea.TextContent;
Assert.AreEqual("100", outputAreaText);
}
Assert.IsNotNull(razorComponent.Instance.challenges);
}
The #input is missing..Why??
Thanks in advance!
I am guessing the problem is that you do not cause the component under test to re-render when you assign
razorComponent.Instance.challengesproperty/field, and if the component does not re-render, then the markup inside@if ((challenges != null) && (challenges.Count > 0))block in the component is not displayed.In general, dont mutate properties (parameters) of components through the
razorComponent.Instance. If you really have to do so, make sure to trigger a render after.Instead, pass parameters to the component through the
RenderComponentor SetParametersAndRender methods, or through services injected into components. That will cause the component to go through its normal render life-cycle methods.