在单元测试中,为什么要创建两次存储库?


10

前几天,我在阅读有关单元测试的内容时,看到了一些示例,人们在其中创建了一个存储库界面(即IExampleRepository),然后创建了真实的存储库(public class ExampleRepository : IExampleRepository)和一个用于单元测试的存储库(FakeExampleRepository : IExampleRepository)。

在中,IExampleRepository他们实现了与中相同的方法ExampleRepository,但是使用了不同的Linq查询。

确切的目的是什么?我认为对代码进行单元测试的一部分是确保一种方法正常工作吗?但是,当我使用两个完全不同的查询时,一个用于“真实”查询,另一个在测试中,该测试有多大意义?

Answers:


8

单元测试的目的之一是一次只测试一件事,即单一类和方法。如果存储库本身不在测试中,那么您通常会以某种方式对此进行模拟,以便仅测试您的方法/类中的逻辑。

也就是说,您还需要使用“真实的”存储库进行测试*,但这通常会在集成/系统测试中完成

* 显然是真实的,如用于测试的回购中那样,希望不是生产数据库。


因此,在单元测试中,我不会测试该方法本身以确保它返回正确的值(基于伪造/模拟的数据集)吗?
2013年

是的,您将测试方法本身,但方法中的代码,其他对象中的代码应包含在其他单元测试中,集成测试或更高级别的测试
jk)

1
好的,因此,如果我理解正确,则在对存储库进行单元测试时应使用原始存储库。我并不需要对其进行测试时,我编写单元测试的控制器(在Asp.Net MVC的情况下)
饶宗颐

4
@Theomax取决于上下文:如果您要不是您的软件组件进行单元测试ExampleRepository,那么最好使用模拟。理由是您不是要对存储库进行单元测试,而是进行其他测试。
Andres F.

5
@Theomax扩展AndresF。的评论:如果您正在进行单元测试ExampleRepository,请使用真实的东西。如果您正在进行单元测试RepositoryController,则应使用FakeExampleRepository返回预定值的。这样,如果错误蔓延到ExampleRepository,则只有该单元测试将失败- RepositoryController的测试将继续成功,因此您知道那里没有错误。如果控制器使用的实际存储库,他们会被都失败,你不会不知道,如果你有1个错误或2
Izkata

5

我同意jk的两个回答。和Jan Hudec-他们提供了一些非常好的信息。但我想我会补充一点。

您的第一个问题(“目标到底是什么?”)很重要。在您描述的情况下,真正的目标是测试利用该IExampleRepository接口的类,而不是测试存储库实现。创建FakeExampleRepository可以让您测试那些客户端类而不必担心真实存储库类的细节。

如果您要设置的对象使测试变得困难(例如访问文件系统,调用Web服务或与数据库对话),则尤其如此。通过使用接口(和其他此类技术),可以保持较低的耦合。因此,类X仅需要了解接口,而无需了解实现细节。目的是确保班级X做正确的事。

模拟(或存根,伪造……有细微的差别)是用于单元测试和TDD的强大工具。但是手动创建和维护这些实现可能会很痛苦。因此,大多数语言现在都具有模拟库来提供帮助。由于您使用的是C#,因此我建议您使用Moq,因为它既简单又非常强大。然后,您可以针对接口进行测试,而无需为模拟实现堆积额外的代码。


the real objective is to test the classes that are utilizing the IExampleRepository interface并非完全正确。目的是独立于IExampleRepository 进行测试。+1虽然推荐了一个好的隔离框架。
StuperUser 2013年

1
我不同意。它不是独立于的,IExampleRepository因为被测试的类已耦合到该接口。但是它独立于接口的任何实现。我承认我的解释可能会使用更多技巧。:)
艾伦(Allan)2013年

5

确切的目的是什么?

隔离。

单元测试的思想是测试尽可能小的代码单元。您可以通过它与测试中的所有其他生产代码隔离开来。

通过创建伪造的类,唯一的生产代码就是要测试的类。

如果您正确创建了一个伪造的存储库,并且测试失败,那么您就会知道问题出在被测试代码。这为您带来了免费诊断的好处。

有一个在隔离框架(如起订量由@Allan的建议),以能够快速生成这些假货设置的测试条件,并利用它们来对断言。


假货,嘲弄和存根更多细节:stackoverflow.com/questions/346372/...
StuperUser

4

您可能要提供模拟实例以进行单元测试的三个原因:

  1. 您希望限制测试的范围,以使测试不受depndee中错误的影响,这可能是因为它尚未完成或不稳定,或者您不希望其他人的错误影响您的测试。
  2. 受抚养人的安置很复杂。例如,经常会嘲笑数据访问层,因为真正的访问层需要建立一个测试数据库。您仍然需要测试真实的数据访问层,但是在调试其他内容时可以限制昂贵的设置。
  3. 为了测试依赖类对各种错误的正确反应,您提供了一个模拟版本,该版本返回各种错误答案。因为许多故障模式很难重现,但仍应进行测试。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.