【问题标题】:Binding an attribute to a validator for SpecFlow unit testing将属性绑定到验证器以进行 SpecFlow 单元测试
【发布时间】:2026-01-17 21:35:01
【问题描述】:

所以,我正在使用我的团队正在使用 SpecFlow 测试的 MVC 应用程序。我使用[RequiredIf(prop, val)] 的实现,描述为here

但是,我发现了一个“轻微”问题 - 虽然验证在网页上运行良好,但它们会破坏我们的单元测试!经过调查,我发现在我们的单元测试中直接调用了属性的 IsValid() 方法……可能是因为属性没有绑定到验证器。

在那个博客上,我按照设置步骤向验证器注册了RequiredIf 属性。但是,出于某些单元测试的目的,我需要找出在测试设置中绑定验证的位置。

我尝试了一些或多或少的逻辑选项:

[Binding]
public class TestSteps
{
     // Every test has to call this helper to load up the controller...
     private void GoToHome()
     {
         // SNIP: Unimportant
         DataAnnotationsViewModelValidatorProvider.RegisterAdapter(..., ...);
     }
}

...以及在测试套件文件中...

// See attribute for why I figured this may be a logical choice.
[BeforeScenario]
public void Setup()
{
    DataAnnotationsViewModelValidatorProvider.RegisterAdapter(..., ...);
}

...然而,出于某种原因,这两个位置都不会导致RequiredIf() 绑定到它的RequiredIfValidator()

问题:对于单元测试,我应该将 Attribute -> Validator 绑定放在哪里,这样我的单元测试才能正确验证在 RequiredIf() 时修饰的属性?

【问题讨论】:

    标签: c# asp.net-mvc-3 unit-testing validation specflow


    【解决方案1】:

    我不得不承认我不熟悉 MVC 验证,所以这可能有效,也可能无效。

    但是,我猜如果你单独使用 NUnit,你可能想做这样的事情

    [FixtureSetup]
    public void ....()
    {
        DataAnnotationsViewModelValidatorProvider.RegisterAdapter(..., ...);
    }
    

    目前,您实际上是通过绑定添加验证,这是一个完整的反射跳。

    但是,如果您查看自动生成的 xxxxx.feature.cs 文件,您可以看到该类实际上定义为

    [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.8.1.0")]
    [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [NUnit.Framework.TestFixtureAttribute()]
    [NUnit.Framework.DescriptionAttribute("xxxxx")]
    public partial class xxxxxFeature
    {
    

    显然我们不能编辑它,但我们可以创建另一个文件来实现我们喜欢的部分类中的任何内容。

    在 xxxxx.partial.cs 中

    public partial class xxxxxFeature
    {
         [FeatureSetup]
         ....
    

    如果不出意外,您还有几个地方可以尝试。祝你好运。

    【讨论】:

    • 感谢您的建议!现在,我决定为我的RequiredIf.IsValid() 实现增加更多责任,不再需要注册。感谢您考虑答案 - 即使我们想不出一个答案:(