您好,登录后才能下订单哦!
小编给大家分享一下Java单元测试Powermockito和Mockito使用的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>2.8.9</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>1.7.4</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito2</artifactId> <version>1.7.4</version> <scope>test</scope> </dependency>
Mockito、EasyMock、JMock等比较流行Mock框架有个共同的缺点,都不能mock静态、final、私有方法等,而PowerMock可以完美解决以上框架的不足,接下来让我们看看无所不能的PowerMock是如何解决上述问题,我们先从一个实例来看,下面的代码是需要单测的类,被测类中既有对Spring Bean的调用,同时又包含对Redis的静态读取,另外还有getInstance()单例类的使用,现在,我们一一来mock上述的外部类。
被单测类(主要测试queryStudentScoreByKeyword方法)
@Component
public class StudentService {
    @Resource
    private StudentDao studentDao;
    public List<StudentBo> queryStudentScoreByKeyword(String name) {
        System.out.println("invoke StudentService.queryStudentScoreByKeyword ...");
        List<StudentBo> cacheList = RedisUtils.getArray(name, StudentBo.class);
        if (CollectionUtils.isNotEmpty(cacheList)) {
            return cacheList;
        }
        String keyword = processKeyword(name);
        List<Student> students = studentDao.queryStudentByKeyWord(keyword);
        List<Integer> ids = students.stream().map(Student::getId).collect(Collectors.toList());
        List<Person> personList = SchoolManageProxy.getInstance().queryPerson(ids);
        List<StudentBo> studentBos = CommonUtils.toBo(personList, students);
        // 高亮结果
        highlightResult(studentBos, name);
        // 缓存到Redis
        RedisUtils.setArray(name, studentBos, 10 * 60);
        return studentBos;
    }
    private String processKeyword(String name) {
        System.out.println("invoke StudentService.processKeyword ...");
        String newName = name;
        // do somethings
        return newName;
    }
    private void highlightResult(List<StudentBo> result, String name) {
        System.out.println("invoke StudentService.highlightResult ...");
        // do keyword highlight
    }
}单测类
@RunWith(PowerMockRunner.class)
@PrepareForTest({SchoolManageProxy.class, RedisUtils.class, StudentService.class})
// @PowerMockIgnore({"javax.management.*", "javax.net.ssl.*"})
@SuppressStaticInitializationFor({"cn.ganzhiqiang.ares.unittest.SchoolManageProxy"})
public class StudentServiceTest {
    @Mock
    private StudentDao mockStudentDao;
    @InjectMocks
    private StudentService studentServiceUnderTest;
    @Before
    public void setUp() {
        initMocks(this);
    }
    @Test
    public void testQueryStudentScoreByKeyword() throws Exception {
        studentServiceUnderTest = PowerMockito.spy(studentServiceUnderTest);
        PowerMockito.mockStatic(RedisUtils.class);
        PowerMockito.mockStatic(SchoolManageProxy.class);
        // mock单例调用
        SchoolManageProxy mockSchoolManageProxy = PowerMockito.mock(SchoolManageProxy.class);
        PowerMockito.when(SchoolManageProxy.getInstance()).thenReturn(mockSchoolManageProxy);
        when(mockSchoolManageProxy.queryPerson(anyList())).thenReturn(Collections.emptyList());
        // mock掉对Redis的静态调用
        PowerMockito.when(RedisUtils.getArray(eq("tom"), eq(StudentBo.class))).thenReturn(Collections.emptyList());
        // 显示的mock掉静态的void的方法(可以不mock)
        PowerMockito.doNothing().when(RedisUtils.class, "setArray", anyString(), anyList(), anyInt());
        // mock私有方法processKeyword
        PowerMockito.doReturn("tom").when(studentServiceUnderTest, "processKeyword", anyString());
        // 跳过私有方法highlightResult的执行
        PowerMockito.suppress(PowerMockito.method(StudentService.class, "highlightResult"));
        // 使用Mockito来mock服务的调用
        when(mockStudentDao.queryStudentByKeyWord(anyString())).thenReturn(Collections.emptyList());
        // Run the test
        final List<StudentBo> result = studentServiceUnderTest.queryStudentScoreByKeyword("tom");
    }
}首选我们先用Mockito来mock对Spring Bean的调用,Mockito.mock可以mock一个实例,我们这里选用@Mock注解,效果是一样的。
// 使用Mockito来mock服务的调用 when(mockStudentDao.queryStudentByKeyWord(anyString())).thenReturn(Collections.emptyList());
接下来我们使用PowerMock来mock对静态方法的调用,注意需要将RedisUtils类,加入@PrepareForTest注解中,我们既mock了getArray方法,也mock了setArray方法,其实setArray不需要mock这里显式的mock了
PowerMockito.mockStatic(RedisUtils.class);
// mock掉对Redis的静态调用
PowerMockito.when(RedisUtils.getArray(eq("tom"), eq(StudentBo.class))).thenReturn(Collections.emptyList());
// 显式的mock掉静态的void的方法(可以不mock)
PowerMockito.doNothing().when(RedisUtils.class, "setArray", anyString(), anyList(), anyInt());mock单例类相对来说复杂一点,逻辑上先用Powermock mock出单例类,然后再给单例类的getInstance方法打桩,返回之前mock,再对mock类实际调用的方法打桩即可,代码如下
PowerMockito.mockStatic(SchoolManageProxy.class); // Powermock mock出单例类 SchoolManageProxy mockSchoolManageProxy = PowerMockito.mock(SchoolManageProxy.class); // 给单例类的getInstance方法打桩 PowerMockito.when(SchoolManageProxy.getInstance()).thenReturn(mockSchoolManageProxy); // 对mock类queryPerson的方法打桩 when(mockSchoolManageProxy.queryPerson(anyList())).thenReturn(Collections.emptyList());
可以看到queryStudentScoreByKeyword方法调用了该类的私有方法processKeyword,如果该方法耗时过长,使用powermock也可以mock该私有方法,需要注意的studentServiceUnderTest需要用spy()来mock
// mock 实例
// spy的标准是:如果不打桩,默认执行真实的方法,如果打桩则返回桩实现。
studentServiceUnderTest = PowerMockito.spy(studentServiceUnderTest);
// mock私有方法processKeyword
// doReturn(...) when(...)不做真实调用,但是when(...) thenReturn(...)还是会真实调用原方法,只是返回了指定的结果
PowerMockito.doReturn("tom").when(studentServiceUnderTest, "processKeyword", anyString());使用PowerMock也可以跳过私有方法的执行
// 跳过私有方法highlightResult的执行 PowerMockito.suppress(PowerMockito.method(StudentService.class, "highlightResult"));
看完了这篇文章,相信你对“Java单元测试Powermockito和Mockito使用的示例分析”有了一定的了解,如果想了解更多相关知识,欢迎关注亿速云行业资讯频道,感谢各位的阅读!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。