Junit单元测试+aop+spring+线程池,在进行Junit测试时切面中线程池内调用的方法不执行
一、问题背景:
写了一个切面,指向某service包下的所有类及方法,当该service包下方法被调用时切面执行,切面中用了线程池ExecutorService pool = Executors.newFixedThreadPool(5);线程池内调用了dao层的方法。
二、问题描述:单元测试时,切面中的部分代码执行了,切面中线程池中调用dao的方法没有执行。
三、相关代码:
1、切入点方法代码
public class MyService {
@Autowired
private JdbcOperations jdbcTemplate;public void m1(UserVo vo) {
System.out.println("我是m1切入点方法......");
}public void m2(List<UserVo> list) {
System.out.println("我是m2切入点方法......");
}
public void m3() {
System.out.println("我是m3切入点方法......");}
}
2、切面类相关代码:
public class ServiceEventAdvice {
private static Logger logger = LoggerFactory.getLogger(ServiceEventAdvice.class);
@Autowired
private ISaveEvent oracleSaveEvent;
public void before(final JoinPoint jp) throws NoSuchMethodException {
//打成jar放入到halo框架下需放开下面代码
// final Map<String, String> map = new HashMap<>();
// Observable.just(HeaderInfoHolder.getInboundHeader()).subscribe(new Observer<HeaderInfo>() {
// //从报文头中获取调用方ESB-ORISYS和交易流水号 ESB-TRANNO的值
// @Override
// public void onCompleted() {
// logger.info("观察者HeaderInfo接收数据完毕");
// }
//
// @Override
// public void onError(Throwable e) {
// logger.info("观察者HeaderInfo接收数据异常");
// }
//
// @Override
// public void onNext(HeaderInfo t) {
// String orginSystem = ((CxfHeader)t).getOrginSystem();
// String tcode = ((CxfHeader)t).getTransactionCode();
// map.put("orginSystem", orginSystem);
// map.put("tcode", tcode);
// }
// });
//
// String tcode = map.get("tcode")==null ? "":map.get("tcode");
// String orginSystem = map.get("orginSystem")==null ? "":map.get("orginSystem");
// logger.info("本次截获报文头的交易流水号tcode是:" + tcode + ",方法调用方是:" + orginSystem);
System.err.println("对外暴露服务的切面开始执行...");
String tcode = "tcode";
String orginSystem = "orginSystem";
Timestamp occurTime = new Timestamp(System.currentTimeMillis());
String methodName = jp.getSignature().toString();
Object[] objects = jp.getArgs();
SaveEventVO obj = new SaveEventVO();
obj.setMethodName(methodName);
obj.setTcode(tcode);
obj.setOrginSystem(orginSystem);
obj.setPtxId("ptxId");
obj.setBusinessNo("");
obj.setAopType("A");
obj.setOccurTime(occurTime);
ExecutorService pool = Executors.newFixedThreadPool(5);
pool.execute(new Runnable(){
public void run() {
byte[] buf = null;
if (objects.length != 0) {
for (Object obj : objects) {
if (obj instanceof List<?>) {
@SuppressWarnings("unchecked")
List<Object> list = (List<Object>) objects[0];
buf = SerializeUtil.serializeList(list);
}else {
buf = SerializeUtil.serializeObject(objects[0]);
}
}
}
System.out.println("11111111111");
oracleSaveEvent.save(buf,obj);//在单元测试中,该行代码没有执行
System.out.println("222222222222");//在单元测试中,该行代码没有执行
}
});
}
}
3、单元测试类代码:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:generalevent/applicationContext-generalevent.xml"})
public class MyServiceTest {
@Autowired
MyService myService;
@Autowired
ISaveEvent saveEvent;
@Test
public void myServiceTest(){
System.err.println("myService=" + myService + ",saveEvent="+ saveEvent);
Address address1 = new Address("addr111", "beijing");
Address address2 = new Address("addr222", "shanghai");
UserVo vo = new UserVo("a123", "lsl", 21,address1);
UserVo vo2 = new UserVo("b456", "mjx", 21,address2);
List<UserVo> list = new ArrayList<UserVo>();
list.add(vo);
list.add(vo2);
myService.m2(list);
}}
4 、运行结果截图:
四、问题原因
在做单元测试时,切面中线程池中的线程还没有开始启动,而主线程已经关闭了,造成切面类中标颜色的两行代码没有执行。
五、解决办法
在单元测试方法中最后加入一行代码:System.in.read();,不让主线程关闭。就ok了。即标色部分:
@Test
public void myServiceTest(){
System.err.println("myService=" + myService + ",saveEvent="+ saveEvent);
Address address1 = new Address("addr111", "beijing");
Address address2 = new Address("addr222", "shanghai");
UserVo vo = new UserVo("a123", "lsl", 21,address1);
UserVo vo2 = new UserVo("b456", "mjx", 21,address2);
List<UserVo> list = new ArrayList<UserVo>();
list.add(vo);
list.add(vo2);
myService.m2(list);
try {
System.in.read();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}