C# Specflow测试步骤继承原因“;“步骤定义不明确”;

C# Specflow测试步骤继承原因“;“步骤定义不明确”;,c#,inheritance,specflow,acceptance-testing,ambiguous,C#,Inheritance,Specflow,Acceptance Testing,Ambiguous,我希望具有以下测试步骤类结构: [Binding] public class BaseStep { [Given(@"there is a customer")] public void GivenThereIsACustomer(Table table) { HandleCustomer(table); } protected virtual void HandleCustomer(Table table) { } }

我希望具有以下测试步骤类结构:

[Binding]
public class BaseStep
{
    [Given(@"there is a customer")]
    public void GivenThereIsACustomer(Table table)
    {
        HandleCustomer(table);
    }

    protected virtual void HandleCustomer(Table table)
    {
    }
}

[Binding]
public class FeatureOneStep : BaseStep
{
    protected override void HandleCustomer(Table table)
    {
         // feature one action
    }

    [Given(@"feature one specific step")]
    public void GivenFeatureOneSpecificAction(Table table)
    {
        // do something
    }

}

[Binding]
public class FeatureTwoStep : BaseStep
{
    protected override void HandleCustomer(Table table)
    {
         // feature two action
    }

    [Given(@"feature two specific step")]
    public void GivenFeatureTwoSpecificAction(Table table)
    {
        // do something
    }
}
“给定有客户”是FeatureOne和FeatureTwo中使用的常见步骤,但这两个功能中的处理逻辑不同。所以我决定将这个步骤定义放在一个基类中,并分别重写两个派生类中的受保护方法

但是,当我运行测试时,出现以下错误:

TechTalk.SpecFlow.BindingException: Ambiguous step definitions found for step
'Given there is a customer': 
CustomerTestBase.GivenThereIsACustomer(Table),   
CustomerTestBase.GivenThereIsACustomer(Table)

有谁能告诉我如何解决这个问题吗?

答案很简单;不要使用继承来定义绑定


在运行时,SpecFlow通过全局扫描所有公共类来查找具有匹配
[给定]
属性的方法,从而找到要调用的方法。这意味着您不能为同一个
提供两个不同的实现,因为存在一个客户
声明,如果您认为这是一个非常明智的设计决策,可以减少歧义。

现在我自己就知道了,所以有几点注意事项(希望将来有人可以使用):

  • 不要在基类上包含[Binding]属性
  • 为每个要素文件创建衍生类
    • 将[Binding]属性添加到派生类(将自动包括基类中的所有步骤定义)
    • 向派生类添加[Scope]属性;指定命名参数要素的要素名称

    • 这对我来说很有效:

      public class BaseSteps
      {
          [Given(@"Method called")]
          public virtual void WhenMethodCalled()
          {
      
          }
      }    
      
      
      
      [Binding]
      [Scope(Feature= "specific_feature")
      public class DerivedSteps : BaseSteps
      {
          [Given(@"Method called")]
          [Scope(Feature= "specific_feature", Tag ="specific_tag")]
          public override void WhenMethodCalled()
          {
      
          }
      }
      

      他是对的。只有在控制初始化时,继承才起作用。由于测试是自动生成的,所以您无法定义将使用哪个具体类。您可以编写一个步骤来进行构造,如果您一直坚持使用继承,则可以调用子类。1-基类bc=FeatureOneClass();公元前2年。特征一步;如果基类是抽象的,我相信这种推理不适用。SpecFlow应该只对具体类感兴趣,但它似乎扫描得太松散了。这是正确的答案。我知道SpecFlow不希望我们使用继承,但在我看来,这是一个不必要的令人困惑的设计选择。面向对象编程技术已经提供了强大的代码重用方法。为什么要重新发明轮子?它成功了!这是@RunOfTheShipe答案的编码示例