我正在尝试为Feign客户端的实现编写单元测试。我不确定该怎么做,所以我用谷歌搜索了一下,遇到了这个答案,接受的答案是这个代码片段:
@Test
public someTestClient(){
Person expectedPerson = new Person("name",12));
when(mockPersonClient.getPerson()).return(expectedPerson);
Person person = mockPersionClient.getPerson();
assertEquals(expectedPerson, person);
}
我不明白为什么这是一个有用的测试,或者在什么情况下,除了Person
构造函数的问题之外,这个测试可能会失败。这个测试本质上不是等同于:
Person person = new Person("a", 1)
Person expectedPerson = new Person("a", 1)
assertEquals(person, expectedPerson)
我知道单元测试应该单独测试功能。此测试是否只会确保mockPersonClient
在运行时存在?
我们可以配置一个模拟对象,以便在对该模拟对象调用方法时始终返回硬编码和假对象。
在这个例子中,OP被配置为返回一个假Person
mockPersonClient.getPerson()
。不过,他只是想知道为什么那个假人没有按照配置回来mockPersonClient.getPerson()
。我认为他展示的代码示例只是为了证明这个问题。这并不意味着他实际上编写了单元测试代码来测试某些生产代码。
这样的测试没有任何价值。
这是一个人,我将要求这个电话返回人,然后我会在打电话给那个东西时检查我得到了人。当然你会得到人,你只是硬编码了它,那么它有什么用呢?
单元测试是关于功能的,这是一个简单的事实,许多人都丢失了。 任何更改数据、过滤某些内容、以受控方式更改某些内容的代码都是单元测试的良好候选者。
人们使用模拟的次数有点太多了,而且大多数时候都是为了错误的事情。是的,建议我们针对接口进行编码,但这并不意味着您应该拥有一个非常复杂的系统,您可以在其中传递到各个地方的接口,然后您的测试代码尝试模仿它。
当你模拟太多时,这意味着你正在编写的测试与它测试的代码绑定得太多,它对它了解得太多了。单元测试不应该这样做,因为每次你以某种小的方式更改代码时,你都会发现现在你必须改变测试,因为你不再使用 35 个接口,现在你有 47 个接口可以按非常特定的顺序进行模拟。当您进行一次测试时,这可能不是问题,但是想象一下当您进行 1000 次测试时会发生什么......
如果人们试图以更实用的方式进行编码,那么这就不会发生。如果你传递数据,而不是抽象,现在你不必模拟任何东西。
与其模拟调用数据库,隔离它,获取结果并将其传递给方法,你只是丢失了一个抽象,你的代码不需要模拟任何东西,你只需调用该方法,以你想要的任何格式传递数据,看看会发生什么。
如果要测试真实的数据库,请编写集成测试。这真的没有那么复杂,嘲笑不应该是你做的第一件事,当它有帮助并且你真的必须这样做时,但大多数时候,你真的没有,如果你不这样做,它会简化事情。