【发布时间】:2016-12-04 06:05:25
【问题描述】:
假设我有一个 UserRepository 结构,它封装了与数据库交互的逻辑。该结构有一组方法,例如:
- findAll()
- findById()
- findByName()
- 保存()
- 等等....
还有另一个依赖于 UserRepository 结构的结构(我们称之为 UserService)。
要测试 UserService,我需要模拟 UserRepository 的功能。我知道这样做的唯一方法是为 UserRepository 提供接口并使 UserService 依赖于它而不是 UserRepository 结构。它将允许创建接口的模拟实现并将其设置为测试中 UserService 的依赖项。
最惯用的方法是什么?
1) 如果 UserService 仅依赖于 1 个 UserRepository 的方法(比如说 findAll)——我应该仍然定义一个包含所有存储库方法的接口,还是最好只为这个方法定义一个单独的接口并将其用作用户服务?如果是这样,它的最佳名称是什么(接口)?如果另一个结构将依赖于 findAll() 和 findById() 方法,我应该再次创建另一个接口吗?
2) 为这些接口存储模拟的最佳位置在哪里?是否可以重复使用它们?或者对于不同结构的测试,我需要重新定义模拟?
附:对我来说,单元测试是项目中非常重要的一部分。我想让它们尽可能地可读,避免样板代码并专注于它们的逻辑。因此,在不同的测试文件中为相同的接口创建多个模拟实现对我来说是一个糟糕的选择,因为它会降低测试代码的可读性。
【问题讨论】:
-
我不知道这是否被认为是惯用的,但我的直觉是为 UserRepository 创建一个具有您需要的最小表面积的接口(目前只有一种方法)。如果它正在与 MongoDb 交谈,我会将接口 UserRepository 和结构称为更具体的实现,例如 MongoUserRepository
-
您可以创建一个名为
mocks_test.go的文件并将您的模拟文件保存在其中。只要该文件与您的其他测试在同一个包中,他们就可以使用模拟。同样,我不知道这是否会被认为是惯用的。 -
问题是用这种方法我最终会得到很多接口。 FindAll() 方法的一个接口。 FindByName() 方法的另一个接口。 FindAll() 和 FindById() 方法等组合的第三个接口。我不能将它们都称为 UserRepository。
-
我不是在暗示。创建一个接口并根据接口调用者的需要放入尽可能多的方法。你不应该在没有被另一个结构调用的接口中添加任何额外的东西。
-
在我看来你正在尝试用 Go 编写 Java。
标签: unit-testing testing go