使用 Moq 和 Unity 模拟存储库对象以进行单元测试的正确方法
在我的工作中,我们使用 Moq 进行模拟,使用 Unity 进行 IOC 容器。我对此相当陌生,工作中没有太多资源来帮助我确定应该使用的最佳实践。
现在,我有一组存储库接口(例如:IRepository1、IRepository2...IRepository4),特定进程需要使用它们来完成其工作。
在实际代码中,我可以通过使用 IOC 容器并使用 RegisterType() 方法来确定所有 IRepository 对象。
我正在尝试找出能够测试需要上述 4 个存储库的方法的最佳方法。
我想我可以注册一个新的 Unity IOC 容器实例,并为每个模拟对象调用容器上的 RegisterInstance,传入每个模拟对象的 Mock.Object 值。我试图使这个注册过程可重用,这样我就不必在每个单元测试中一遍又一遍地做同样的事情,除非单元测试需要从存储库返回一些特定的数据。这就是问题所在......在模拟存储库上设置期望值的最佳实践是什么?看起来如果我只在 Unity 容器上调用 RegisterType,我就会丢失对实际 Mock 对象的引用,并且无法覆盖行为。
At my job we are using Moq for mocking and Unity for an IOC container. I am fairly new to this and do not have many resources at work to help me out with determining the best practices I should use.
Right now, I have a group of repository interfaces (Ex: IRepository1, IRepository2... IRepository4) that a particular process needs to use to do its job.
In the actual code I can determine all of the IRepository objects by using the IOC container and using the RegisterType() method.
I am trying to figure out the best way to be able to test the method that needs the 4 mentioned repositories.
I was thinking I could just register a new instance of the Unity IOC container and call RegisterInstance on the container for each mock object passing in the Mock.Object value for each one. I am trying to make this registration process reusable so I do not have to keep doing the same thing over and over with each unit test unless a unit test requires some specific data to come back from the repository. This is where the problem lies... what is the best practice for setting up expected values on a mocked repository? It seems like if I just call RegisterType on the Unity container that I would lose a reference to the actual Mock object and would not be able to override behavior.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
单元测试根本不应该使用容器。依赖注入 (DI) 分为两个阶段:
如何完全不使用任何 DI 容器进行单元测试
作为示例,请考虑使用 IRepository1 的类。通过使用构造函数注入模式,我们可以使依赖成为类的不变量。
请注意,如果实例成功实例化,
readonly
关键字与 Guard Clause 相结合可保证repository
字段不为 null。您不需要容器来创建 MyClass 的新实例。您可以使用 Moq 或其他测试替身直接从单元测试中执行此操作:
请参阅此处 了解更多信息...
如何使用 Unity 进行单元测试
但是,如果您绝对必须在测试中使用 Unity,则可以创建容器并使用 RegisterInstance 方法:
Unit tests should not use the container at all. Dependency Injection (DI) comes in two phases:
How not to use any DI Container at all for unit testing
As an example, consider a class that uses IRepository1. By using the Constructor Injection pattern, we can make the dependency an invariant of the class.
Notice that the
readonly
keyword combined with the Guard Clause guarantees that therepository
field isn't null if the instance was successfully instantiated.You don't need a container to create a new instance of MyClass. You can do that directly from a unit test using Moq or another Test Double:
See here for more information...
How to use Unity for unit testing
However, if you absolutely must use Unity in your tests, you can create the container and use the RegisterInstance method: