单元测试框架PowerMock

1.概述

Mockito 是一个针对 Java 的单元测试模拟框架,它与 EasyMock 和 jMock 很相似,都是为了简化单元测试过程中测试上下文的搭建而开发的工具。
  PowerMock 也是一个单元测试模拟框架,它是在其它单元测试模拟框架的基础上做出的扩展。通过提供定制的类加载器以及一些字节码篡改技巧的应用,PowerMock 现了对静态方法、构造方法、私有方法以及 Final 方法的模拟支持,对静态初始化过程的移除等强大的功能。

2.引入依赖

		<dependency>
			<groupId>org.powermock</groupId>
			<artifactId>powermock-api-mockito</artifactId>
			<version>1.7.4</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.mockito</groupId>
			<artifactId>mockito-all</artifactId>
			<version>1.8.5</version>
		</dependency>

3.代码示例

单元测试用到的类:

public interface StudentDao {
	String queryStudent();
}

public interface StudentService {
	
	public String selectStudentByName();
	
	public String selectStudentByName2();
}

@Repository
public class StudentDaoImpl implements StudentDao {

	@Override
	public String queryStudent() {
		
		return "拿着核武器的程序员";
	}

}

@Service
public class StudentServiceImpl implements StudentService {

	@Autowired
	private StudentDao studentDao;

	// 正常方法
	@Override
	public String selectStudentByName() {
		// 调用了私有方法
		String student = getNameById();
		System.out.println("method:selectStudentByName" + student);
		return student;
	}

	// 正常方法
	@Override
	public String selectStudentByName2() {
		String name = StudentServiceImpl.selectStudentById();
		System.out.println("静态方法返回值:" + name);
		return name;
	}

	// 静态方法
	public static String selectStudentById() {
		System.out.println("------------------");
		return "拿着大炮的男孩";
	}

	private String getNameById() {
		String student = studentDao.queryStudent();
		System.out.println("method:getNameById" + student);
		return student;
	}

	public final String getAgeById() {
		System.out.println("----------------");
		return "拿着大炮的男孩";
	}
}

单元测试类:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ StudentServiceImpl.class })
public class StudentServiceTest {

	/**
	 * spy()方法:表示局部mock,执行方法的时候会进入具体的方法内,spy的作用是让被测类正常工作,但是可以拦截某些方法的返回值
	 * 比如让StudentServiceImpl中的selectStudentByName()正常工作,但是返回值可以是我们期望的值
	 * mock()方法:表示全局mock,执行方法的时候不会进入到具体方法内
	 */

	/**
	 * 使用powermock的测试类需要加@RunWith(PowerMockRunner.class)
	 * 若需要模拟构造函数、私有方法、static方法、final方法都需要在测试类上添加注解
	 * 
	 * @throws Exception
	 * @PrepareForTest({ 被Mock的类 })
	 * 
	 *  1.测试私有方法
	 */
	@Test
	public void test() throws Exception {
		// 局部mock
		StudentServiceImpl serviceImpl = PowerMockito.spy(new StudentServiceImpl());
		// 在selectStudentByName中调用了私有方法,此时需要对私有方法mock
		// 若有参数,就在后面使用Mockito.anyXxx()
		// 由于私有方法中又使用了自动注入的StudentDao,所以mock StudentDao然后通过Whitebox(白盒)替换属性
		StudentDao studentDao = PowerMockito.mock(StudentDao.class);
		// 第一个参数:需要被替换属性的对象 ;第二个参数:属性名 ; 第三个参数:属性值
		Whitebox.setInternalState(serviceImpl, "studentDao", studentDao);
		PowerMockito.doReturn("hahahaha").when(studentDao).queryStudent();
		PowerMockito.when(serviceImpl, "getNameById").thenReturn("东皇太一");
		serviceImpl.selectStudentByName();
	}

	/**
	 * 2.测试静态方法 
	 * 想要单元测试selectStudentByName2()方法,但是该方法中使用了静态方法
	 */
	@Test
	public void test2() {
		// 模拟静态方法前需要先调用这一句,不写会报错!!!
		PowerMockito.mockStatic(StudentServiceImpl.class);
		// 模拟当执行静态方法StudentServiceImpl.selectStudentById()时候,返回123(模拟的返回值)
		PowerMockito.when(StudentServiceImpl.selectStudentById()).thenReturn("123");
		StudentServiceImpl serviceImpl = PowerMockito.spy(new StudentServiceImpl());
		serviceImpl.selectStudentByName2();
	}

	/**
	 * 3.测试final方法
	 */
	@Test
	public void test3() {
		StudentServiceImpl service = PowerMockito.mock(StudentServiceImpl.class);
		PowerMockito.when(service.getAgeById()).thenReturn("18");
		String age = service.getAgeById();
		System.out.println(age);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_27466827/article/details/84797115