使用构造器方式初始化
项目中大量使用了构造器方式注入,这种注入方式的好处有下列几种。
· 使用final关键字,保证依赖不可变
· 省去了我们对其检查,保证依赖不为空
· 保证返回客户端(调用)的代码的时候是完全初始化的状态
· 避免了循环依赖
· 提升了代码的可复用性
特别是循环依赖检查这方面,随着业务的扩展,当初的代码结构设置的不够合理,对代码不够熟悉等因素可能造成循环依赖的情况。之前发生过项目上线后,点击了相关功能才爆出系统异常,原因就是产生了循环依赖。使用了构造器注入方式后,在项目启动的时候,就会抛出BeanCurrentlyInCreationException:Requested bean is currently in creation: Is there an unresolvable circular reference从而提醒避免循环依赖。
这种场景可以直接使用@Mock和@InjectMocks
业务代码示例
@Service
public class EventService implements ModuleDtoQuery<EventDetailDTO> {
private final AppService appService;
private final EventRepo repo;
@Autowired
public EventService(AppService appService,
EventRepo repo) {
this.appService = appService;
this.repo = repo;
}
}
单元测试代码示例
@RunWith(PowerMockRunner.class)
public class EventServiceTest {
@Mock
AppService appService;
@Mock
EventRepo repo;
@InjectMocks
EventService eventService;
@Test
public void queryList() {
...
}
}
构造器注入中加入了List -> Map
通过接口注入了多个实现,再通过List转Map来达到快速获得接口、减少代码的目的。
业务代码示例
@Service
public class CatalogService {
private final CatalogRepo catalogRepo;
private final CatalogAssembler catalogAssembler;
private final Map<Integer, CountByCatalog> countByCatalogMap;
@Autowired
public CatalogService(CatalogRepo catalogRepo,
CatalogAssembler catalogAssembler,
List<CountByCatalog> countByCatalogList) {
this.catalogRepo = catalogRepo;
this.catalogAssembler = catalogAssembler;
this.countByCatalogMap = countByCatalogList.stream()
.collect(Collectors.toMap(CountByCatalog::getCatalogType, v -> v));
}
}
单元测试代码示例
首先使用@Mock来模拟这个接口的集合,再手动写一些实现类,这样就可以达到我们模拟的要求了。
@RunWith(PowerMockRunner.class)
@PrepareForTest({SpringContextUtils.class})
public class CatalogServiceTest {
@Mock
CatalogRepo catalogRepo;
@Mock
CatalogAssembler catalogAssembler;
@Mock
List<CountByCatalog> countByCatalog = Arrays.asList(new CountByCatalog() {
@Override
public int getCatalogType() {
return 0;
}
});
@InjectMocks
CatalogService catalogService;
}
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理