基于PowerMockito的静态方法的多种mock测试方式 小结 您所在的位置:网站首页 powermock私有方法无覆盖率 基于PowerMockito的静态方法的多种mock测试方式 小结

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

2024-07-12 03:56| 来源: 网络整理| 查看: 265

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

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

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

4.12 2.19.0 2.0.0-beta.5 org.mockito mockito-core ${mockito-core.version} junit junit ${junit4.version} test org.powermock powermock-module-junit4 ${powermock.version} test org.powermock powermock-api-mockito2 ${powermock.version} test

注:因为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 listObjOfBucket(S3Client s3, String bucket, String path) { ListObjectsV2Request listReq = ListObjectsV2Request.builder() .bucket(bucket) .prefix(path) .maxKeys(1) .build(); ListObjectsV2Iterable listRes = s3.listObjectsV2Paginator(listReq); List result = new ArrayList(); SdkIterable 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()); 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的源码下载链接。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有