StructureMap 在 NUnit 测试之间不会重置

发布于 2024-08-14 12:14:04 字数 625 浏览 2 评论 0原文

我正在测试一些使用 StructureMap 进行控制反转的代码,当我对同一接口使用不同的具体类时,就会出现问题。

例如:

[Test]
public void Test1()
{
    ObjectFactory.Inject<IFoo>(new TestFoo());

    ...
}

[Test]
public void Test2()
{
    ObjectFactory.Initialize(
        x => x.ForRequestedType<IFoo>().TheDefaultIsConcreteType<RealFoo>()
    );
    // ObjectFactory.Inject<IFoo>(new RealFoo()) doesn't work either.

    ...
}

如果 Test2 使用 RealFoo 自行运行,则可以正常工作。但如果 Test1 首先运行,Test2 最终会使用 TestFoo 而不是 RealFoo。 NUnit 测试不应该是隔离的吗?如何重置 StructureMap?

奇怪的是,如果我不包含初始化表达式,Test2 就会失败。但如果我确实包含它,它就会被忽略......

I'm testing some code that uses StructureMap for Inversion of Control and problems have come up when I use different concrete classes for the same interface.

For example:

[Test]
public void Test1()
{
    ObjectFactory.Inject<IFoo>(new TestFoo());

    ...
}

[Test]
public void Test2()
{
    ObjectFactory.Initialize(
        x => x.ForRequestedType<IFoo>().TheDefaultIsConcreteType<RealFoo>()
    );
    // ObjectFactory.Inject<IFoo>(new RealFoo()) doesn't work either.

    ...
}

Test2 works fine if it runs by itself, using a RealFoo. But if Test1 runs first, Test2 ends up using a TestFoo instead of RealFoo. Aren't NUnit tests supposed to be isolated? How can I reset StructureMap?

Oddly enough, Test2 fails if I don't include the Initialize expression. But if I do include it, it gets ignored...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

拧巴小姐 2024-08-21 12:14:04

如果必须在测试中使用 ObjectFactory,请在 SetUp 或 TearDown 中调用 ObjectFactory.ResetAll()。

更好的是,尝试将代码从对 ObjectFactory 的依赖中迁移出来。任何需要从容器中取出内容的类(启动方法除外)都可以接受 IContainer,它将自动由 StructureMap 填充(假设类本身是从容器中检索的)。您可以通过 ObjectFactory 的 Container 属性来引用由 ObjectFactory 包装的 IContainer。您还可以完全避免使用 ObjectFactory,而只创建一个您自己管理的 Container 实例(可以使用与 ObjectFactory 相同的方式进行配置)。

If you must use ObjectFactory in your tests, in your SetUp or TearDown, make a call to ObjectFactory.ResetAll().

Even better, try to migrate your code away from depending on ObjectFactory. Any class that needs to pull stuff out of the container (other than the startup method) can take in an IContainer, which will automatically be populated by StructureMap (assuming the class itself is retrieved from the container). You can reference the IContainer wrapped by ObjectFactory through its Container property. You can also avoid using ObjectFactory completely and just create an instance of a Container that you manage yourself (it can be configured in the same way as ObjectFactory).

愿得七秒忆 2024-08-21 12:14:04

是的,NUnit 测试应该是隔离的,并且有责任确保它们是隔离的。解决方案是在测试装置的 TearDown 方法中重置 ObjectFactory。例如,您可以使用 ObjectFactory.EjectAllInstancesOf() 。

Yes, NUnit tests are supposed to be isolated and it is your responsibility to make sure they are isolated. The solution would be to reset ObjectFactory in the TearDown method of your test fixture. You can use ObjectFactory.EjectAllInstancesOf() for example.

烟酉 2024-08-21 12:14:04

当然,它不会在测试之间重置。 ObjectFactoryInstanceManager 的静态包装器;它通过 AppDomain 是静态的,并且当测试在同一个 AppDomain 中运行时,这就是它不被重置的原因。您需要TearDown 测试之间的 ObjectFactory 或为每个测试配置一个新的 Container(即,避免使用静态 ObjectFactory)。

顺便说一句,这是避免全局状态和单例的主要原因:它们对测试不友好。

来自 Google 指南编写可测试代码

全局状态:从理论、可维护性和可理解性的角度来看,全局状态很糟糕,但只要您有一个应用程序实例,全局状态在运行时是可以容忍的。但是,与生产中应用程序的一个实例相比,每个测试都是应用程序的一个小实例。全球状态从一次测试持续到下一次测试,并造成了大规模的混乱。测试是单独运行的,但不是一起运行的。更糟糕的是,测试一起失败,但问题无法单独重现。测试的顺序很重要。 API 并不清楚初始化和对象实例化的顺序等等。我希望现在大多数开发人员都同意全局状态应该像 GOTO 一样对待。

Of course it doesn't reset between tests. ObjectFactory is a static wrapper around an InstanceManager; it is static through an AppDomain and as tests run in the same AppDomain this is why it is not reset. You need to TearDown the ObjectFactory between tests or configure a new Container for each test (i.e., get away from using the static ObjectFactory).

Incidentally, this is the main reason for avoiding global state and singletons: they are not friendly to testing.

From the Google guide to Writing Testable Code:

Global State: Global state is bad from theoretical, maintainability, and understandability point of view, but is tolerable at run-time as long as you have one instance of your application. However, each test is a small instantiation of your application in contrast to one instance of application in production. The global state persists from one test to the next and creates mass confusion. Tests run in isolation but not together. Worse yet, tests fail together but problems can not be reproduced in isolation. Order of the tests matters. The APIs are not clear about the order of initialization and object instantiation, and so on. I hope that by now most developers agree that global state should be treated like GOTO.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文