BlueXIII's Blog

热爱技术,持续学习

0%

研发规约-jUnit测试

简介

工程必须编写Junit单元测试,只有通过所有测试并达到指定覆盖率之后,才允许构建。

初期不强制要求,视团队接受/排斥情况而定

约定

存放及命名

所有单元测试均放在src/test/java文件夹下,命名为类名+Test(s).java,即对于某个类的所有单元测试均放在同一个文件内

Jacoco代码覆盖率

工程必须配置Jacoco插件,以进行代码测试覆盖率的检查,只有覆盖率达到一定比例才能通过构建。更多细节请参考Sonar代码检测.md

准备工作

pom.xml

修改zorrodemo.service模块的pom.xml,添加mockito依赖

1
2
3
4
5
6
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>

Service层单元测试DEMO

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
@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(会小幅度增加开发复杂度,根据情况权衡)