如何在 Blazor 中修复这个简单的 ElementNotFoundException?

问题描述

我正在对 blazor 应用进行单元测试。我得到一个 ElementNotFoundException。我认为造成这种情况的原因是 index.razor 页面中的 if 语句。见下面的代码

<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>

这个页面后面的代码(index.razor.cs)有如下初始化代码

protected override async Task OnInitializedAsync()
    {
        jsonRepository = new JSONChallengeRepository();
        challenges = await jsonRepository.GetChallengesAsync();
    }

页面的测试在这里

[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);
    }

缺少#input..为什么??

提前致谢!

解决方法

我猜问题是你在分配razorComponent.Instance.challenges属性/字段时没有导致被测组件重新渲染,如果组件没有重新渲染,那么{{ 1}} 组件中的块不显示。

一般来说,不要通过 @if ((challenges != null) && (challenges.Count > 0)) 来改变组件的属性(参数)。如果您确实必须这样做,请确保trigger a render之后。

相反,pass parameters to the component 通过 razorComponent.InstanceSetParametersAndRender 方法,或通过 services injected 进入组件。这将导致组件经历其正常的渲染生命周期方法。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...