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();
        }

        
    } 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
aopcontext.currentproxy() 是一个用于切面编程的方法,它用于获取当前代理对象。 在进行单元测试,我们常常需要验证目标方法是否被正确地拦截和执行增强逻辑。这,可以通过调用 aopcontext.currentproxy() 方法来获取当前的代理对象,然后使用该代理对象来调用目标方法,并在测试代码进行断言。 举个例子,假设我们有一个 UserService 接口和一个 UserServiceImpl 实现类,其 UserServiceImpl 类上添加了一个自定义的切面逻辑。在进行单元测试,我们可以使用 Mockito 或其他测试框架来创建 UserService 的 Mock 对象,并在测试方法引入切面逻辑进行验证。 具体实现如下: ```java import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.springframework.aop.framework.AopContext; import static org.mockito.Mockito.when; public class UserServiceTest { @Mock private UserDao userDao; @InjectMocks private UserServiceImpl userService; @Test public void testUserService() { // 创建 Mock 对象,并预设一些行为 User expectedUser = new User("test", "123456"); when(userDao.findUserByUsername("test")).thenReturn(expectedUser); // 获取 UserService 的代理对象 UserService userServiceProxy = (UserService) AopContext.currentProxy(); // 调用代理对象的方法进行测试 User resultUser = userServiceProxy.getUserByUsername("test"); // 进行断言验证 assertEquals(expectedUser, resultUser); } } ``` 在上述示例,我们使用了 Mockito 框架来创建 UserService 的 Mock 对象,并模拟了 `userDao.findUserByUsername("test")` 方法的返回值。然后,我们通过调用 `AopContext.currentProxy()` 方法获取代理对象 `userServiceProxy`,并使用该代理对象调用 `getUserByUsername()` 方法。最后,我们使用断言方法 `assertEquals` 对实际结果和预期结果进行验证。 通过使用 aopcontext.currentproxy() 方法,我们可以方便地在单元测试验证切面逻辑是否正确地拦截和执行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一路奔跑1314

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值