在大型依赖对象图上注入模拟
对于我想要测试的对象,我有一个相当重要的依赖关系图。解决依赖关系而无需到处注册模拟的最简单方法是什么?
例如,我有一个像这样的依赖关系图:
PublicApi
ApiService
AccountingFacade
BillingService
BillingValidation
BillingRepository
UserService
UserRepository
我想测试 PublicApi.CreateUser()
,并且我希望它运行所有代码,但我想模拟存储库,所以我不'不必向数据库写入任何内容。我是否应该只使用 DI 容器并注册所有服务,用模拟替换存储库,然后解析 PublicApi
并运行该方法?
我正在研究 AutoFixture,看起来它可能能够处理类似的事情,但我无法完全理解整个“冻结”与“注册”及其与起订量的集成。
I have a a fairly significant dependency graph for an object I want to test. What is the easiest way to resolve my dependencies without having to register mocks everywhere?
For example, I have a dependency graph like this:
PublicApi
ApiService
AccountingFacade
BillingService
BillingValidation
BillingRepository
UserService
UserRepository
I want to test PublicApi.CreateUser()
, and I want it to run through all the code, but I want to mock the repositories so I don't have to write anything to the database. Should I just use a DI container and register all my services, replacing the repositories with mocks, then resolve PublicApi
and run the method?
I was looking into AutoFixture, and it looks like it might be able to handle something like this, but I can't quite wrap my head around the whole 'Freeze' vs 'Register' and it's integration with Moq.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
对于单元测试,您应该只模拟直接依赖项。在您的情况下,您创建
PublicApi
并为ApiService
注入模拟,并验证PublicApi
是否使用上的正确值调用适当的方法。 >ApiService
模拟。以同样的方式测试与更深层次依赖项隔离的所有其他组件。
如果您想测试多个组件的组合,那么这不是单元测试,而是集成测试。因此,这取决于您如何将课程组合在一起。例如,如果您使用 IoC 容器,它可能支持以某种方式替换存储库的配置。在这种情况下,您可以使用应用程序的配置并用模拟替换存储库,也可能用模拟替换视图。
For Unittests you should only mock the direct dependencies. In your case you create
PublicApi
and inject a mock forApiService
and verify ifPublicApi
is calling the appropriate methods with the correct values on theApiService
Mock.The same way you test all the other components isolated from the deeper dependencies.
If you want to test the combination of several components, that isn't unit testing but rather integration testing. Therefore it depends of how you are putting your classes together. e.g. if you are using an IoC container, it probably supports replacing the configuration for the repositories in some way. In this case you can use the configuration of the application and replace the repositories and potentially also the views with mocks.
这可能一点帮助都没有,但我还是要说。
看来您试图一次测试太多,为什么不只测试 BillingService -> BillingValidation,然后BillingService -> BillingRepository 等。通过这种方式,您将拥有一套测试来证明每个测试都有效,然后当您到达 PublicApi 层时,您只需要模拟 ApiService,因为您已经测试了其下面的所有内容,因此测试没有任何价值再来一次。
一般来说,我一次只会测试一层,但我不知道你的完整场景,所以你可能有一些我没有考虑到的东西,所以如果是这种情况,并且你真的需要一起测试所有这些,我只会带来在像 Ninject 之类的简单轻量级 DI 框架中。
这样你就可以将所有类型绑定到模拟,然后从中实例化你的 PublicApi。
对于ninject,它看起来像这样:
虽然你必须问自己,你在这里测试什么?如果它只是交互,我会像我首先提到的那样做,如果它更多,那么也许会考虑后一个选择。不管怎样,我希望它能给你一些选择。
This may not be helpful in the least but I will say it anyway.
It seems you are trying to test too much at once, why not just test BillingService -> BillingValidation, then BillingService -> BillingRepository etc. This way you would have a suite of tests proving that each one works, then when you are up at the PublicApi Layer you only need to mock ApiService, as you have already tested everything beneath it, so there is no value in testing it again.
Generally I will only test 1 layer at a time, but I dont know your full scenario so you may have something which I am not accounting for, so if this is the case and you REALLY need to test all of this together I would just bring in a simple and lightweight DI framework like Ninject or something.
This way you can just bind all your types to mocks, then instanciate your PublicApi from it.
With ninject it would look something like:
Although you have to ask yourself, what are you testing here? if its just interactions I would do as I first mention, if its more then maybe think about the latter choice. Either way I hope it gives you some options.