You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在无EditForm时测试包含InputText的_Item组件?

问题描述

遇到如下错误:

System.InvalidOperationException : Microsoft.AspNetCore.Components.Forms.InputText requires a cascading parameter of type EditContext. For example, you can use Microsoft.AspNetCore.Components.Forms.InputText inside an EditForm.

_Item组件代码:

@if (UtiliseItemCostum())
{
    <div class="form-group mt-3">
        <label>Item</label>
        @if (EpicerieDetailsUtiliseItemCustom())
        {
            <InputText id="itemNonEnregistre" @bind-Value="EpicerieDetailsDto.ItemCustom"></InputText>
        }
        else if (GabaritDetailsUtiliseItemCustom())
        {
            <InputText id="itemNonEnregistre" @bind-Value="GabaritDetailsDto.ItemCustom"></InputText>
        }
    </div>
}
else
{
    <_MenuDeroulantItems EpicerieDetailsDto="@EpicerieDetailsDto" GabaritDetailsDto="@GabaritDetailsDto" />
}

该组件在父组件的EditForm中可正常运行,父组件核心代码如下:

<EditForm Model="EpicerieDetailsDto" OnValidSubmit="GererEpicerieDetails">
    <!-- 其他表单元素 -->
    <_Item EpicerieDetailsDto="@EpicerieDetailsDto"/>
    <!-- 其他表单元素 -->
</EditForm>

但执行测试代码时,InputText因缺失EditContext报错,测试代码如下:

public static IEnumerable<TestCaseData> ItemTestCases()
{
    yield return new TestCaseData(null, new EpicerieDetailsDto() { UtiliseItemCustom = true });
    yield return new TestCaseData(new GabaritDetailsDto() { UtiliseItemCustom = true }, null);
}

[Test]
[TestCaseSource(nameof(ItemTestCases))]
public void QuandChangeCheckBox_AlorsChangeChoixItem(GabaritDetailsDto gabarit, EpicerieDetailsDto epicerie)
{
    var cut = _testContext.RenderComponent<_Item>(parametres => 
        parametres
            .Add(p => p.EpicerieDetailsDto, epicerie)
            .Add(p => p.GabaritDetailsDto, gabarit)
    );

    Assert.NotNull(cut.Find("#itemNonEnregistre"));
}

需求:通过模拟EditForm环境测试该含InputText的组件。


解决方案

要解决测试时EditContext缺失的问题,有两种可靠实现方式:

方式一:用EditForm包裹待测试组件

直接在测试中把_Item组件嵌套在EditForm内部,传入对应的Dto作为EditForm的Model,自动生成所需的EditContext。修改后的测试代码如下:

[Test]
[TestCaseSource(nameof(ItemTestCases))]
public void QuandChangeCheckBox_AlorsChangeChoixItem(GabaritDetailsDto gabarit, EpicerieDetailsDto epicerie)
{
    // 确定EditForm使用的Model(和传入_Item的Dto一致)
    var formModel = epicerie ?? gabarit;

    var cut = _testContext.RenderComponent<EditForm>(parameters => parameters
        .Add(p => p.Model, formModel)
        .AddChildContent(_testContext.CreateComponent<_Item>(childParams => childParams
            .Add(p => p.EpicerieDetailsDto, epicerie)
            .Add(p => p.GabaritDetailsDto, gabarit)
        ))
    );

    Assert.NotNull(cut.Find("#itemNonEnregistre"));
}

方式二:手动传入CascadingValue

如果不需要完整的EditForm功能,可直接通过CascadingValue组件手动注入EditContext,模拟EditForm的核心依赖:

[Test]
[TestCaseSource(nameof(ItemTestCases))]
public void QuandChangeCheckBox_AlorsChangeChoixItem(GabaritDetailsDto gabarit, EpicerieDetailsDto epicerie)
{
    var model = epicerie ?? gabarit;
    var editContext = new EditContext(model);

    var cut = _testContext.RenderComponent<CascadingValue<EditContext>>(parameters => parameters
        .Add(p => p.Value, editContext)
        .AddChildContent(_testContext.CreateComponent<_Item>(childParams => childParams
            .Add(p => p.EpicerieDetailsDto, epicerie)
            .Add(p => p.GabaritDetailsDto, gabarit)
        ))
    );

    Assert.NotNull(cut.Find("#itemNonEnregistre"));
}

注意事项

  • 两种方式都要保证EditContext的Model和_Item组件使用的Dto完全一致,避免绑定异常。
  • 如果组件依赖表单验证(如ValidationMessage),优先选择方式一,因为EditForm会自动初始化验证相关上下文。

内容的提问来源于stack exchange,提问作者Christoff Colomb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 08:00:00