一般来说,Spring应用的单元测试都是发生在该应用的某个层,例如controller、service或者是dao层。 而service层既是应用服务的主要实现者,也是重点被测试的对象,其余各层,如controller层一般以线性代码为主,缺少业务逻辑,可以少测甚至是不测。 不过也有些团队会认为,既然应用的入口是controller,那么从controller层入口对服务进行测试,更贴合用户的场景,这部分的测试也更有业务价值,也更能提升对产品质量的信心。如果某些测试场景或者分支是通过controller层无法达到的,那么这部分的测试优先级就可以降低。 因此,笔者就见到过controller连同service一起进行测试的场景,也就是所谓的跨层单元测试 还是以TestLink4J为例,有如下用例
package com.testlink4j.controller;
//import
@Slf4j
public class KeywordsControllerServiceTest {
@InjectMocks
private KeywordsServiceImpl keywordsService;
@InjectMocks
KeywordsRestController keywordsRestController;
@Mock
KeywordsMapper keywordsMapper;
@BeforeEach()
public void setup() {
MockitoAnnotations.initMocks(this);
ReflectionTestUtils.setField(keywordsRestController,
"keywordsService",keywordsService);
}
@Test
public void CreateKeywordsSuccessfullyTest() {
Keywords keywords=Keywords.builder().id(666).keyword("tester")
.testproject_id(333).notes("tester").build();
Mockito.when(keywordsMapper.selectByPrimaryKey(1)).thenReturn(keywords);
Keywords responseString=keywordsRestController.findKeywordById(1);
log.info(JSON.toJSONString(responseString));
assertThatJson(responseString).isEqualTo(keywords);
}
}
用例调用了keywordsRestController.findKeywordById方法,并验证其返回结果,实现了对keywordsRestController和keywordsService的测试,也就是controller和service两层的测试。 以下是执行的日志:
22:01:36.569 [main] DEBUG org.springframework.test.util.ReflectionTestUtils - Setting field 'keywordsService' of type [null] on target object [com.testlink4j.controller.KeywordsRestController@422c3c7a] or target class [class com.testlink4j.controller.KeywordsRestController] to value [com.testlink4j.service.impl.KeywordsServiceImpl@18230356]
22:01:36.747 [main] INFO com.testlink4j.controller.KeywordsControllerServiceTest - {"id":666,"keyword":"tester","notes":"tester","testproject_id":333}
这其中的运行逻辑是这样的
简单介绍一下案例中的代码是如何实现上述逻辑的,
MockitoAnnotations.initMocks(this);
ReflectionTestUtils.setField(keywordsRestController,
"keywordsService",keywordsService);