Technical note
研发规约-jUnit测试
简介
工程必须编写Junit单元测试,只有通过所有测试并达到指定覆盖率之后,才允许构建。
初期不强制要求,视团队接受/排斥情况而定
约定
存放及命名
所有单元测试均放在src/test/java文件夹下,命名为类名+Test(s).java,即对于某个类的所有单元测试均放在同一个文件内
Jacoco代码覆盖率
工程必须配置Jacoco插件,以进行代码测试覆盖率的检查,只有覆盖率达到一定比例才能通过构建。更多细节请参考Sonar代码检测.md。
准备工作
pom.xml
修改zorrodemo.service模块的pom.xml,添加mockito依赖
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
Service层单元测试DEMO
public class AttachmentServiceUnitTest {
private static final Logger log = LoggerFactory.getLogger(AttachmentServiceUnitTest.class);
@InjectMocks
private AttachmentService attachmentService = new AttachmentService();
@Mock
private AttachmentMapper attachmentMapper;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void query() {
List<Attachment> attachmentList = new ArrayList<>();
Attachment attachment = new Attachment();
attachment.setId("1");
attachment.setName("attachmentName");
attachmentList.add(attachment);
given(attachmentMapper.query(Mockito.any(String.class))).willReturn(attachmentList);
PageInfo<Attachment> result = attachmentService.query("1.docx", 1, 10);
log.info("result: {}", result);
assertTrue(result.getTotal() > 0);
}
}
Service层集成测试DEMO
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = RootApplicationContextConfigForTest.class)
@Transactional //事务默认回滚
public class AttachmentServiceIntegrationTest {
private static final Logger log = LoggerFactory.getLogger(AttachmentServiceIntegrationTest.class);
@Autowired
private AttachmentService attachmentService;
@Test
public void save() {
Attachment attachment = new Attachment();
attachment.setId("1");
attachment.setName("test1");
attachment.setPath("/tmp");
int result = attachmentService.save(attachment);
log.info("result: {}", result);
assertEquals(1, result);
}
@Test(expected = DataIntegrityViolationException.class)
public void saveWithException() {
Attachment attachment = new Attachment();
attachment.setId("1");
int result = attachmentService.save(attachment);
log.info("result: {}", result);
assertEquals(1, result);
}
@Test
public void query() {
PageInfo<Attachment> result = attachmentService.query("1.docx", 1, 10);
log.info("result: {}", result);
assertTrue(result.getTotal() > 0);
}
@Test
public void queryWithNotExistName() {
PageInfo<Attachment> result = attachmentService.query("notexist", 1, 10);
log.info("result: {}", result);
assertEquals(0, result.getTotal());
}
@Test
public void delete() {
Attachment attachment = new Attachment();
attachment.setId("1");
attachment.setName("test0");
attachment.setPath("/tmp");
attachmentService.save(attachment);
int result = attachmentService.delete("1");
log.info("result: {}", result);
assertTrue(result > 0);
}
}
Controller层集成测试
- 无法使用
@SpringBootTest,不容易实现 - 公司框架中controller层基本上无业务逻辑,仅是rest接口的定义。本层测试省略后影响较小。
关于回归测试
- 方式1: 利用IDEA自带的HTTP client实现。
- 方式2: 使用更通用的postman+newman编写测试脚本并测试
- 不强制回归测试
- 更多细节参考
接口回归测试.md
其它说明
- 尽量简化开发流程,降低上手难度,除公司标准框架外,不引入新的复杂度
- 不做TDD,不做每个层级的单元测试
- 仅做service层的集成测试
- 为避免数据不一致造成的测试失效,后期可考虑引入H2 Database(会小幅度增加开发复杂度,根据情况权衡)