基于PowerMockito的静态方法的多种mock测试方式 小结

1. 在使用PowerMockito之前,首先要了解到Mockito这个测试工具,因为PowerMockito就是基于Mockito增强了一些功能,比如静态方法的测试。这里的可以参考:基于Mockito的多层模拟单元测试 小结

2. 网上有很多PowerMockito mock静态方法的总结,以下主要是针对这几天使用过程中遇到的各种问题,从mock公共静态方法私有方法两个方面进行总结。

3. 首先先是PowerMockito的pom.xml的依赖。

<properties>
	<junit4.version>4.12</junit4.version>
	<mockito-core.version>2.19.0</mockito-core.version>
	<powermock.version>2.0.0-beta.5</powermock.version>
</properties>

<dependencies>
	<dependency>
		<groupId>org.mockito</groupId>
		<artifactId>mockito-core</artifactId>
		<version>${mockito-core.version}</version>
	</dependency>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>${junit4.version}</version>
		<scope>test</scope>
	</dependency>	
	<dependency>
		<groupId>org.powermock</groupId>
		<artifactId>powermock-module-junit4</artifactId>
		<version>${powermock.version}</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>org.powermock</groupId>
		<artifactId>powermock-api-mockito2</artifactId>
		<version>${powermock.version}</version>
		<scope>test</scope>
	</dependency>
</dependencies>

:因为PowerMockito是根据Mockito进行增强的,相应版本依赖要求比较严格。

如果遇到:java.lang.NoSuchMethodError: org.mockito.internal.handler.MockHandlerFactory.createMockHandler... 就是pom.xml里面的依赖版本不对了。 

4. PowerMockito mock私有方法

1) 假设以下的S3Util需要被mock测试。

public class S3Util {

    public S3Util() {
    }

    private void call(String output) {
        System.out.println(output);
    }
    
    public ByteBuffer getRandomByteBuffer(int size) {
        byte[] b = new byte[size];
        new Random().nextBytes(b);
        call("123123123123");
        System.out.println(222);
        return ByteBuffer.wrap(b);
    }

}

2) 测试,调用public方法。

@RunWith(PowerMockRunner.class)
@PrepareForTest({S3Util.class})
@PowerMockIgnore({"javax.management.*", "javax.net.ssl.*"})
public class S3UtilTest {
   
    @Mock
    S3Util s3UtilMock;
    @Mock
    S3Client s3Client;

    @Before
    public void before() {
        PowerMockito.mockStatic(S3Util.class);
    }

    @Test
    public void test () throws Exception {
        S3Util s3Util = PowerMockito.spy(new S3Util());
        PowerMockito.doNothing().when(s3Util, "call", anyString());
        s3Util.getRandomByteBuffer(1);
    }

}

输出结果(private方法被mock): 

 

5. PowerMockito mock公有静态方法。

 1) 有返回值的公有静态方法。

  a) 返回String类型。

public static String getFolder(String yyyyMMdd) {
	return "data_date=" + yyyyMMdd + "/";
}
@Test
public void testGetFolder() {
	PowerMockito.when(S3Util.getFolder("20200616")).thenReturn("data_date=20200616/");
	assertEquals("data_date=20200616/", S3Util.getFolder("20200616"));
}

   b) 返回Boolean类型。

public static Boolean copyObject(S3Client s3, String fromBucket, String toBucket, String fromKey, String toKey, boolean skipFileNotFound) {
	String encodedUrl = null;
	try {
		encodedUrl = URLEncoder.encode(fromBucket + "/" + fromKey, StandardCharsets.UTF_8.toString());
	} catch (UnsupportedEncodingException e) {
		System.out.printf("URL could not be encoded: %s", e.getMessage());
		return Boolean.FALSE;
	}

	CopyObjectRequest copyReq = CopyObjectRequest.builder()
			.copySource(encodedUrl)
			.bucket(toBucket)
			.key(toKey)
			.build();

	try {
		CopyObjectResponse copyRes = s3.copyObject(copyReq);
		System.out.printf("copyObject successfully: from %s , to %s\n", fromKey, toKey);
	} catch (S3Exception e) {
		if (e.statusCode() == 404 && skipFileNotFound) {
			System.out.printf("copyObject 404: %s in %s", fromKey, fromBucket);
			return Boolean.TRUE;
		}
		System.out.printf("copyObject s3Exception: %s", e);
		return Boolean.FALSE;
	}

	return Boolean.TRUE;
}
@Test
public void testCopyObject() {
	PowerMockito.when(S3Util.copyObject(Mockito.any(S3Client.class), anyString(), anyString(), anyString(), anyString(), anyBoolean())).thenReturn(true);
	assertEquals(true, S3Util.copyObject(s3Client, "fromBucket", "toBucket", "fromKey", "toKey", false));
}

   c) 返回List类型。

public static List<S3Object> listObjOfBucket(S3Client s3, String bucket, String path) {
			ListObjectsV2Request listReq = ListObjectsV2Request.builder()
			.bucket(bucket)
			.prefix(path)
			.maxKeys(1)
			.build();

	ListObjectsV2Iterable listRes = s3.listObjectsV2Paginator(listReq);
	List<S3Object> result = new ArrayList<>();
	SdkIterable<S3Object> sdkIterable = listRes.contents();
	for (S3Object content : sdkIterable) {
		if (content.size() == 0)
			continue;
		if (null != path) {
			if (content.key().startsWith(path))
				result.add(content);
		} else {
			result.add(content);
		}
	}

	return result;
}
@Test
public void testListObjOfBucket() {
	PowerMockito.when(S3Util.listObjOfBucket(Mockito.any(S3Client.class), anyString(), anyString())).thenReturn(new ArrayList<S3Object>());
	assertNotNull(S3Util.listObjOfBucket(s3Client, "bucketName", "path"));
}

   d) 返回Object类型。

public static S3Client builder(String regionStr) {
	Region region = Region.US_EAST_1;//default region
	if (StringUtils.isNotEmpty(regionStr)) {
		region = Region.of(regionStr);
	}
	return S3Client.builder().region(region).build();
}

public static S3Client builder(Credentials credentials) {
	Region region = Region.US_EAST_1;//default region

	AwsSessionCredentials awsCreds = AwsSessionCredentials.create(
			credentials.accessKeyId(),
			credentials.secretAccessKey(),
			credentials.sessionToken());
	return S3Client.builder().credentialsProvider(StaticCredentialsProvider.create(awsCreds)).region(region).build();
}
@Test
public void testBuilder() {
	PowerMockito.when(S3Util.builder(anyString())).thenReturn(S3Client.builder().build());
	assertNotNull(S3Util.builder("us-east-1"));

	PowerMockito.when(S3Util.builder(Mockito.any(Credentials.class))).thenReturn(S3Client.builder().build());
	assertNotNull(S3Util.builder(Credentials.builder().build()));
}

   e) 返回byte[]类型。

public static byte[] getS3FileToBytes(S3Client s3, String bucket, String multipartKey) {
	return s3.getObjectAsBytes(GetObjectRequest.builder().bucket(bucket).key(multipartKey).build()).asByteArray();
}
@Test
public void testGetS3FileToBytes() throws Exception {
	byte[] bytes = new byte[]{};
	PowerMockito.when(S3Util.class, "getS3FileToBytes", Mockito.any(S3Client.class), anyString(), anyString()).thenReturn(bytes);
	assertEquals(bytes, S3Util.getS3FileToBytes(s3Client, "bucketName", "multipartKey"));
}

  2) 没有返回值的公有静态方法。

public static void putObject(S3Client s3, String bucket, String key, byte[] bytes) {
	s3.putObject(PutObjectRequest.builder().bucket(bucket).key(key).build(),
			RequestBody.fromByteBuffer(ByteBuffer.wrap(bytes)));
}
@Test
public void testPutObject() throws Exception {
//        PowerMockito.doNothing().when(S3Util.class, "putObject", Mockito.any(S3Client.class), anyString(), anyString() , anyString());
	PowerMockito.doNothing().when(S3Util.class);

	S3Util.putObject(Mockito.any(S3Client.class), anyString(), anyString(), anyString());
	S3Util.putObject(Mockito.any(S3Client.class), anyString(), anyString(), Mockito.any(byte[].class));
}

 

1. 以上的mock方法还可以是:Mockito.doAnswer((invocationOnMock) -> 返回值).when(mock对象).方法名(参数列表);

2. 如果遇到:org.apache.http.conn.ssl.SSLInitializationException: class configured for SSLContext: sun.security.ssl.SSLContextImpl...

在unit-test上面添加:@PowerMockIgnore({"javax.net.ssl.*"})。

3. 如果遇到:ERROR Could not reconfigure JMX java.lang.LinkageError: loader constraint violation: loader...

在unit-test上面添加:@PowerMockIgnore({"javax.management.*"})。

 

: 以上demo的源码下载链接

  • 0
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值