我摆脱了使用JUnit编写基本单元测试的简单方法,该方法将两个数字相加。我可以使用assert *系列函数调用来验证结果。现在,我要对Spring Boot控制器进行单元测试。
这是单元测试类的示例-
public class MyJunitTest {
private MockMvc mockMvc;
@Mock
private MyService service;
@InjectMocks
private MyController controller;
@Before
public void init() {
MockitoAnnotations.initMocks(this);
}
@Test
public void unitTestGetAssessmentDetails() {
when(service.getTest(Someobject.class)).thenReturn(customObjectWithValues);
Results results = controller.getCall(someRequestObject);
assertEquals(results, someOtherObjectPrefilledWithValues);
}
}
我的问题是,如果我知道customObjectWithValues
中设置的值,那么someOtherObjectPrefilledWithValues
也由我设置,那么assertEquals将始终通过测试,对吗?本质上是在测试是否1 == 1种测试。那么进行这些单元测试的重点是什么?我知道该服务对象不应该连接到实际的数据库,因此我们在嘲笑它。那么进行这些测试有什么意义呢?在这里,我是否想了解如何查看单元测试的大图?
P.S。 -如果违反此论坛的规则,请随时删除此问题。
答案 0 :(得分:1)
您的测试验证getCall
返回了预期结果;
这是黑匣子测试。
由于您正在编写单元测试,
这仅足以“假装”执行单元测试。
这种技术在将代码质量与
单元测试代码覆盖率。
一种更好的技术是确定控制器类将要执行的步骤,并验证每个步骤是否已执行(也许也以正确的顺序执行)。
我将假设MyController.getCall
看起来像这样:
@Autowired
private MyService myService;
public BlammyReturnValueType getCall(final BlammyRequestType request)
{
final BlammyReturnValueType returnValue;
returnValue = myService.someServiceMethod(request);
return returnValue;
}
在这种情况下,
我将以下内容添加到unitTestGetAssessmentDetails
测试方法中:
... The current stuff including the assert.
Mockito.verify(service, times(1)).someServiceMethod(customObjectWithValues);
这将确认一次调用了服务方法, 在此示例中是正确的。
答案 1 :(得分:1)
好的,单元测试更多地是关于测试写在函数/控制器/服务中的逻辑。现在,您的功能可能非常简单,也可能非常复杂。例如,您的函数可能正在接受UserId并请求,连接到数据库,获取数据并返回数据,并且由于您正在模拟数据库连接,因此您可能会觉得如果将模拟对象作为数据库响应传递,显然得到相同的响应,那么测试的重点是什么。在这种情况下完全不进行测试似乎是正确的。但是,让我再举一个例子,假设您有一个非常复杂的函数,该函数需要一些UserId,获取银行历史记录的用户的全年数据,对其进行累加并计算今年的用户收入。现在,考虑一下此功能有多复杂。现在,由于模拟了数据库连接,您将传递一些数据,因此内部进行了大量计算,并为用户提供了一定的储蓄利息。现在,对于给定的模拟数据,您知道答案应该为X数量。现在,随着时间的流逝,有人犯了一个错误(也许减去了需要添加的内容)。现在,当您运行测试时。该测试将失败,并且您知道逻辑上有问题。并不是在这里,您不是直接期望输出等于模拟数据,而是对数据进行了一些计算,因此在每次更改后验证功能逻辑是否正确,您需要编写一个单元测试来对其进行验证。现在,如果您在此处看到,您的测试不是1 == 1,而是有所不同。这就是为什么人们编写单元测试,以在代码单元中检查其逻辑的原因。
希望这会有所帮助。
答案 2 :(得分:0)
通常,我们分为3层,分别是控制器,服务,存储库(如果愿意,则为DAO)。我通常不测试控制器,因为我没有在其中添加任何逻辑,我只是定义端点并调用服务。该服务是我进行大量单元测试的工具,因此您可以将模拟注入到您的服务中。然后,您将模拟您的存储库,以便它不会尝试连接到数据库。
@InjectMocks
private MyService service;
@Mock
private MyRepository myrepo
@Test
public void unitTestGetAssessmentDetails() {
when(myrepo.find(someInt)).thenReturn(customObjectWithValues);
Results results = service.serviceMethod(someRequestObject);
assertEquals(results, someOtherObjectPrefilledWithValues);
}
由于控制器应该没有逻辑,所以它们不需要进行单元测试,因为您正确地说这是1 == 1的测试。但是它们将通过集成测试进行测试