Java 当您与dummy&;有接口时,单元测试的最佳方法是什么;真正的实现?
我熟悉TDD的基本原则,即:Java 当您与dummy&;有接口时,单元测试的最佳方法是什么;真正的实现?,java,unit-testing,interface,junit,tdd,Java,Unit Testing,Interface,Junit,Tdd,我熟悉TDD的基本原则,即: 编写测试时,由于没有实现,这些测试将失败 编写基本实现以使测试通过 重构代码 然而,对于接口和实现适合哪里,我有点困惑。我在业余时间创建了一个Spring web应用程序,我想了解如何更好地测试接口/实现,而不是大刀阔斧,以我在这里创建的这个简单示例代码为例: public class RunMe { public static void main(String[] args) { // Using a dummy service
public class RunMe
{
public static void main(String[] args)
{
// Using a dummy service now, but would have a real implementation later (fetch from DB etc.)
UserService userService = new DummyUserService();
System.out.println(userService.getUserById(1));
}
}
interface UserService
{
public String getUserById(Integer id);
}
class DummyUserService implements UserService
{
@Override
public String getUserById(Integer id)
{
return "James";
}
}
我已经创建了UserService
接口,最终会有一个查询数据库的真正实现,但是为了让应用程序启动,我已经用一个DummyUserService
实现代替了,它现在只返回一些静态数据
问题:如何实施上述测试策略?
我可以创建一个名为DummyUserServiceTest
的测试类,并测试当我调用getUserById()
时,它将返回James
,如果不浪费时间的话,看起来非常简单(?)
随后,我还可以创建一个测试类RealUserService
,该类将测试getUserById()
从数据库返回用户名。这是一个让我有点困惑的部分,在这样做的过程中,这是否本质上超出了单元测试的边界,并且变得更像是一个集成测试(在DB上有点击)
问题(改进了一点):当使用带有虚拟/存根和真实实现的接口时,哪些部分应该进行单元测试,哪些部分可以安全地不进行测试?
昨晚我花了几个小时在谷歌上搜索这个话题,主要是找到了关于什么是TDD的教程,或者是如何使用JUnit的示例,但在建议实际应该测试什么方面却没有找到任何东西。但完全有可能的是,我搜索不够努力,或者没有找到正确的东西……不要测试虚拟实现:它们不会在生产中使用。对它们进行测试是没有实际意义的 如果real UserService实现只需转到数据库并通过其ID获取用户名,那么测试应该测试它是否做到了这一点,并且是否正确。如果您愿意,可以称之为集成测试,但它仍然是一个应该编写并自动化的测试
通常的策略是在测试的@Before注释方法中用最少的测试数据填充数据库,并让您的测试方法检查数据库中存在的ID是否返回了相应的用户名。JB的答案很好,我想我应该放弃我使用的另一种技术 在开发原始测试时,首先不要费心删除
UserService
。事实上,继续写真实的东西吧。按照下面的步骤进行
1) 让它发挥作用。
2) 把它做好。
3) 快点
您的代码将进行测试,然后验证findby id是否有效。正如JB所述,此时您的测试将被视为集成测试。一旦他们通过,我们就成功地完成了第一步。现在,看看设计。是这样吗?调整任何设计气味,并从列表中勾选第2步
对于第3步,我们需要快速进行此测试。我们都知道,在所有事务管理和数据库设置中,集成测试都很慢,而且容易出错。一旦我们知道了代码的工作原理,我通常就不必担心集成测试了。此时,您可以引入虚拟服务,有效地将集成测试转化为单元测试。现在它没有以任何方式接触数据库,我们可以从列表中勾选步骤3,因为这个测试现在很快
那么,这种方法有什么问题?很多人会说,我仍然需要对数据库支持的UserService
进行测试。我通常不会在项目中进行集成测试。我的观点是,这些类型的测试是缓慢的、脆弱的,并且在大多数项目中没有捕捉到足够的逻辑错误来为自己买单
希望有帮助
布兰登我建议你先读这本书:史蒂夫·弗里曼和纳特·普赖斯写的。它回答了您和其他许多与TDD相关的问题 在您的特定情况下,您应该使用DB适配器配置您的
RealUserService
,这将进行真正的DB查询。服务本身将支持服务,而不是数据持久性。读这本书,会有很大帮助:)