程序员自测是很重要的一个环节,我认同测试驱动开发的理念,经过一段时间的测试代码的编写,发现测试代码需要保证几点,1.测试代码可重复跑,不能跑过一次,改了数据库数据就不能跑了。2.测试代码写好后,尽可能保持不变,哪怕代码变后,直接跑测试就能验证修改是否正确,而不是把测试代码,测试数据再改一遍。service层测试要与数据库解耦,不能因为数据库数据的变化影响测试,我曾经使用int.sql去对数据库做int操作来保证测试的进行,但是实践过程中会渐渐由于数据表结构更新导致int.sql维护不善,使得每跑一次测试都要修改int.sql。对于十分麻烦的工作,我一般的是不想继续做的,我的想法是无论代码,数据库怎么动,测试代码都是不用怎么改动的,直接跑就可以了,这样也方便项目重构。目前已经达到我对测试的预期了,故而总结现有技术和实现。。如果有更好的建议,也欢迎提出。
mock做service层的单元测试
service测试使用mockito,它可以保证service的获得的业务数据是预期的数据,得到的结果一定是预期的结果。
mockito的作用是动态代理调用替换mapper层,改用自己配置的数据。这样就可以直接做service单层的单元测试。不会出现由于数据库的数据变了,导致单元测试跑不过的情况,直接执行就可以了。
mock数据类
建议做法,创建一个mock数据类,存放所有测试数据 - mock所有的service或者mapper方法,让其返回设定的数据,所有的测试类继承它。
public class MockData {
public static final LockerInfoService lockerInfoService = mock(LockerInfoService.class);
public static final MedicineHistoryService medicineHistoryService = mock(MedicineHistoryService.class);
public static final ParcelService parcelService = mock(ParcelService.class);
public static final ParcelLogService parcelLogService = mock(ParcelLogService.class);
static {
when(lockerInfoService.findByLockerCode("006000001")).thenReturn(createLockerInfo001());
when(lockerInfoService.findByLockerCode("006000002")).thenReturn(createLockerInfo002());
when(medicineHistoryService.findByMHIdInFiveMinute("exist")).thenReturn(createExistMedicineHistory());
when(medicineHistoryService.findByMHIdInFiveMinute("not_exist")).thenReturn(createNotExistMedicineHistory());
when(parcelService.findByParcelCode("1")).thenReturn(createDropOffProcessingParcel());
when(parcelService.findByParcelCode("2")).thenReturn(createAlreadyDropOffParcel());
when(parcelService.findByParcelCode("5")).thenReturn(createAlreadyPickedUpParcel());
when(parcelService.findByPickupCode("006000001","222222")).thenReturn(createAlreadyDropOffParcel());
when(parcelService.findInLockerParcel("006000001", null)).thenReturn(Arrays.asList(createAlreadyDropOffParcel()));
when(parcelService.getEffectiveCodes("006000001")).thenReturn(Arrays.asList(createAlreadyDropOffParcel().getPickupCode()));
when(parcelService.getEffectiveParcels("006000001")).thenReturn(Arrays.asList(createAlreadyDropOffParcel()));
when(parcelService.selectByParcelCode("006000001","1")).thenReturn(createDropOffProcessingParcel());
when(parcelService.selectByParcelCode("006000001","2")).thenReturn(createAlreadyDropOffParcel());
when(parcelService.selectByParcelCode("0060