Spring+PowerMock+Junit

各种杂七杂八问题

什么时候用PrepareForTest

  1. 当使用PowerMockito.whenNew方法时,必须加注解@PrepareForTest和@RunWith。注解@PrepareForTest里写的类是需要mock的new对象代码所在的类。
  2. 当需要mock final方法的时候,必须加注解@PrepareForTest和@RunWith。注解@PrepareForTest里写的类是final方法所在的类。 
  3. 当需要mock静态方法的时候,必须加注解@PrepareForTest和@RunWith。注解@PrepareForTest里写的类是静态方法所在的类。
  4. 当需要mock私有方法的时候, 只是需要加注解@PrepareForTest,注解里写的类是私有方法所在的类
  5. 当需要mock系统类的静态方法的时候,必须加注解@PrepareForTest和@RunWith。注解里写的类是需要调用系统方法所在的类

PowerMock无法mock掉spring的PostContruct

假如你的postConstruct中含有如下代码:

@PostContruct
public void init() {
          XRepository.query();
}
你会发现你没法mock掉XRepository的行为,这是因为引入spring体系后,最典型的是比如使用@Sql注解的时候,会引入一些TestExecutionListener,这些spring专用的listener会要求spring进行上下文初始化,要求bean的初始化,而这些初始化可能在@BeforeClass之前,@Before之前,测试类的静态代码块之前,导致你没有办法通过常规的junit的常规手段将postConstruct中的内容mock掉。

在经过很多资料搜索后,此处使用的办法是使bean在初始化的过程中无法执行postConstruct方法,直接断其根源,一旦spring尝试调用postConstruct方法,就返回一个假的方法调用,而不是尝试对postConstruct代码块中一些需要mock的元素作提前mock。

package com.vip.spring;

import lombok.SneakyThrows;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils;

import javax.annotation.PostConstruct;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class MockitoSpyBeanPostProcessor implements BeanPostProcessor {

    @SneakyThrows
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 用于忽略postConstruct注解
        Class<?> userClass = ClassUtils.getUserClass(bean);
        Method[] allDeclaredMethods = ReflectionUtils.getAllDeclaredMethods(userClass);
        List<Method> collect = Arrays.stream(allDeclaredMethods).filter(method -> AnnotationUtils.findAnnotation(method, PostConstruct.class) != null).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(collect)) {
            return bean;
        }
        Object spy = PowerMockito.spy(bean);
        Method postConstructMethod = collect.get(0);

        PowerMockito.doAnswer(new Answer<Object>() {
            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                Object[] args = invocation.getArguments();
                Object mock = invocation.getMock();
                return null;
            }
        }).when(spy, postConstructMethod.getName());

        return spy;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

这样这个testCase不就变成一个goodCase了吗?

记一次单元测试 java.lang.ClassCastException: com.sun.crypto.provider.HmacSHA1 cannot be cast to javax.crypto.MacSpi

在用单元测试Junit测试部门的SDK时,有个md5鉴权步骤,出现了java.lang.ClassCastException: com.sun.crypto.provider.HmacSHA1 cannot be cast to javax.crypto.MacSpi错误,经排查是Junit编写问题,在@Test下面新增@PowerMockIgnore("javax.crypto.*")即可成功通过测试!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
junit4和powermock是两个常用的Java测试框架,它们常被开发人员用来进行单元测试。 junit4是一个成熟的单元测试框架,用于编写和运行Java程序的测试用例。它可以帮助开发人员在开发过程中及时发现代码中的错误,提升代码的质量。junit4提供了一系列的注解和断言来简化测试用例的编写,并且可以与各种开发工具和持续集成工具进行集成。 与此同时,powermock是一个用于扩展junit4的工具,可以帮助开发人员进行更加灵活和强大的单元测试。它可以模拟和修改Java程序中的一些难以测试的对象和行为,例如静态方法、私有方法和构造函数等。powermock使用了一种称为“字节码操作”的技术,能够改变Java字节码的执行路径,从而达到模拟和修改的目的。 使用junit4和powermock可以让开发人员编写更加全面和准确的单元测试用例。在测试过程中,我们可以使用junit4来编写测试用例的框架和断言,而使用powermock来模拟和修改需要被测试的对象。这样就可以在保持单元测试的独立性和可重复性的同时,更好地模拟和验证代码中的行为。 总的来说,junit4和powermock是两个非常有用的Java测试框架。它们可以一起使用,为开发人员提供更强大和灵活的单元测试能力。通过编写全面和准确的单元测试用例,可以提高代码的质量和可维护性,同时也可以减少程序中的BUG和错误。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值