gpt4 book ai didi

c# - (如何)可以使用 Autofac 作为 IoC 容器运行 Specflow 测试用例?

转载 作者:行者123 更新时间:2023-11-30 13:19:05 25 4
gpt4 key购买 nike

我正尝试在我的组织中采用 BDD,因为 C#.Net 是我们的主要开发模式,Specflow 是我们“任何 Cucumber”的最佳选择。

不过,我过去一直是 Spring 的狂热爱好者,但在我的公司,我们在应用程序的各个部分使用 Autofac。但是,我无法找到任何资源来解释“如何”使用 Autofac 来“触发”Specflow 的 BDD 测试并提供必要的依赖关系连接。

我计划让 Autofac 负责实例化、连接和执行一切,而不是执行 Specflow,并且让调用 Autofac 的方法随处可见,即使用 Autofac 作为服务定位器而不是 DI/IoC 容器。甚至可以做到这一点,还是我以错误的方式看待它并且有更好的方法来实现相同的目标?还是我应该完全依赖 Specflow 的“内部容器”进行 DI 而完全忘记 Autofac?

可能的方法:

  1. 让 Autofac 实例化并连接所有内容并运行 Specflow 测试(不确定这是否可能/推荐)。
  2. 让 Specflow 全局实例化 Autofac,它与代码其余部分的必要依赖关系相连。可能步骤定义可能会使用 Autofac 作为工厂来获得他们需要的东西。

优点/缺点:

  1. 第一种方法是理想的,因为它可以防止从 Specflow 到 Autofac 的任何依赖关系。前者忘记了后者。完全透明。首选,但不确定如何去做。
  2. 如果 Autofac 可以由 Specflow 全局实例化一次供以后使用,则后一种方法“可能”起作用。但这会导致在将两个库耦合在一起的步骤定义中对 Autofac 进行大量调用。不可取。

我不确定如何实现它们中的任何一个,让 Specflow 处理 DI 而忘记 Autofac 还是让 Autofac 启动一切更好,或者是否有一些中间立场更好?

当前的 BDD 设置:Specflow、Selenium/PhantomJS、Xunit。希望与 Autofac 结合。

最佳答案

I plan to have Autofac be responsible for instantiating, wiring and executing everything instead of executing Specflow and have methods calling Autofac littered everywhere.

  • 我真的不明白你如何做到这一点并且仍然能够从 Visual Studio 运行你的测试或 ReSharper (我假设你不想失去它)。

Have Specflow globally instantiate Autofac which is wired with the necessary dependencies for the remainder of the code. Possible that step definitions may land up using Autofac as a factory to get what they need.

  • 这正是我正在做的,也是我推荐的。

But this would lead to lots of calls to Autofac from within the step definitions coupling the two libraries together.

  • 我不建议通过调用 AutoFac 来解析步骤定义类中所需的类型。直接的方法。我会在基类中创建一个方法或将对象绑定(bind)到 specflow 的 mini DI Container说了方法。

我要做的是创建一个名为 IServiceLocator 的服务定位器接口(interface)(是的,我知道 service locator is an antipattern )

public interface IServiceLocator
{
T Get<T>();
}

然后我们将使用 Autofac 创建此接口(interface)的实现(请记住,您可以将其替换为另一个实现)

public class AutoFacServiceLocator: IServiceLocator
{
private readonly IContainer _container;

public AutoFacServiceLocator(IContainer container)
{
_container = container;
}

public T Get<T>()
{
//Here you add your resolution logic
}
}

事实上,对于每个场景,我们都需要一个 IServiceLocator 的实例,我们希望能够通过Specflow得到它的 Context Injection .

[Binding]
public class Hooks
{
private readonly IObjectContainer _objectContainer;

public Hooks(IObjectContainer objectContainer)
{
_objectContainer = objectContainer;
}

[BeforeScenario]
public void RegisterServiceLocator()
{
var container = CreateContainer();

var serviceLocator = new AutoFacServiceLocator(container);

_objectContainer.RegisterInstanceAs<IServiceLocator>(serviceLocator);
}

private IContainer CreateContainer() { /*Create your container*/}
}

最后是用法

[Binding]
public class Steps
{
private readonly IServiceLocator _serviceLocator;

public Steps(IServiceLocator serviceLocator)
{
_serviceLocator = serviceLocator;
}

[Given(@"I have entered (.*) into the calculator")]
public void GivenIHaveEnteredIntoTheCalculator(int p0)
{
Foo foo = _serviceLocator.Get<Foo>();
}
}

更新:

travis-illig在下面的评论中说

If you go with service location, try CommonServiceLocator rather than creating your own interface

我真的不认为有必要使用 CommonServiceLocator .对服务定位器的调用应该与 Controller 中的构造函数注入(inject)相匹配,这意味着这些调用应该被方法 Get<T>() 覆盖。 .

Quoting ctavares , CommonServiceLocator 之一的开发者

Should I use this library for my applications?

Typically, the answer to this question is no. Once you've decided on a container that suits your project, there's not a whole lot of benefit from writing your whole application in a way that can switch containers. For libraries that must fit into other ecosystems and play nicely with other libraries, it's an important feature, but for applications the extra layer of abstraction really doesn't buy you much.

CommonServiceLocator适用于库和框架,因为 PhD的测试项目是他和他的团队的我不建议引入更多依赖项。

关于c# - (如何)可以使用 Autofac 作为 IoC 容器运行 Specflow 测试用例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32387332/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com