如何使用上下文注入在 SpecFlow 中共享步骤绑定 class

How to share step binding class in SpecFlow with context injection

我在 SpecFlow 中使用上下文注入,但我遇到了一个问题,我想共享一个步骤绑定 class,但我不一定需要注册所有构造函数参数。

我在一个单独的 binding/hooks class 中有各种 BeforeScenario 挂钩,我在其中向容器注册对象,如下所示....

[Scope(Scenario = "Scenario A")]
[BeforeScenario(Order = 5)]
public void CreateApprenticeWithChecklist()
{
    //Other stuff

    _container.RegisterInstanceAs<Apprentice>(apprentice);
}

[Scope(Scenario = "Scenario B")]
[BeforeScenario(Order = 5)]
public void CreateApprenticeWithChecklistAllSignOff()
{
    //Other stuff

    _container.RegisterInstanceAs<Apprentice>(apprentice);
    _container.RegisterInstanceAs<Dictionary<string, UserDetails>>(new Dictionary<string, UserDetails>
    {
        ["Employer"] = employer.Key,
        ["Training Provider"] = trainingProvider.Key
    });
}

然后我有一个步骤定义 class 这两个场景都将使用....

[Binding]
public sealed class ApprenticeChecklistSteps
{
    private Apprentice _apprentice;
    private UserDetails _employer;
    private UserDetails _trainingProvider;   

    public ApprenticeChecklistSteps(Apprentice apprentice, Dictionary<string, UserDetails> userDetails)
    {
        _apprentice = apprentice;
        _employer = userDetails["Employer"];
        _trainingProvider = userDetails["Training Provider"];
    }

    //etc

问题是如果我是 运行 Scenario A 将不会有 Dictionary<string, UserDetails> userDetails 的注册,所以我会得到 Multiple public constructors with same maximum parameter count are not supported! 错误。

如果我不一定有或不需要某个构造函数参数,我如何在场景之间共享步骤绑定?

我看到的唯一解决方案是 hacky

为所有未使用的构造函数参数创建 'blank' 注册以便初始化它们

或者...

创建一个包含所有可能注册的单独的 POCO,并在需要时注册我需要的任何内容

public class CheckListContext
{
    public Apprentice Apprentice { get; set; }
    public Dictionary<string, UserDetails> UserDetails { get; set; }
}

场景 A BeforeScenario 中的注册步骤将变为...

_container.RegisterInstanceAs<CheckListContext>(new CheckListContext{Apprentice = apprentice});

您似乎只想在步骤之间共享数据,而不是步骤绑定。在 SpecFlow 中执行此操作的方法是使用场景上下文在一个步骤中设置数据并在另一步骤中检索它。例如,我会有一个名为 Given an apprenticeship exists 的步骤。这个步骤的定义类似于:

[Binding]
public class ApprenticeshipSteps
{
    private readonly ScenarioContext scenario;

    public ApprenticeshipSteps(ScenarioContext scenario)
    {
        this.scenario = scenario;
    }

    [Given(@"an apprenticeship exists")]
    public void GivenAnApprenticeshipExists()
    {
        var apprenticeship = new Apprenticeship(...);

        scenario["apprenticeship"] = apprenticeship;

        // save to database if need be
    }
}

[Binding]
public class MoreStepDefinitions
{

    private readonly ScenarioContext scenario;

    public MoreStepDefinitions(ScenarioContext scenario)
    {
        this.scenario = scenario;
    }

    [Then(@"a step that needs the apprenticeship")]
    public void AnotherStep()
    {
        var apprenticeship = (Apprenticeship)scenario["apprenticeship"];
    }
}

如果需要,您可以将学徒 ID 放在场景上下文中,如果您需要从数据库中获取它的话。场景上下文基本上只是从步骤定义传递到步骤定义的一袋数据。这是在 SpecFlow 中的步骤之间共享数据的首选方式。