简介
工程必须编写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(会小幅度增加开发复杂度,根据情况权衡)