单测编写

tech2022-07-08  179

单元测试的三部曲

打桩,即为非测试目标方法设置返回值,这些返回值在测试目标方法中被使用。执行测试,调用测试目标方法。验证测试结果,如测试方法是否被执行,测试结果是否正确等。

上报测试

/** 被测代码 */ fun reportLikedVideoRemoveExposure(num: String?, feed: stMetaFeed?, rank: String?, userId: String?) { val map = JsonObject() map.addProperty("num", num ?: "") map.addProperty("rank", rank ?: "") map.addProperty("user_id", userId ?: "") Router.getService(BeaconReportService::class.java).reportUserExposure("liked.remove", "1", map.toString(), feed?.id ?: "", feed?.poster_id ?: "") } 这里就使用PowerMock来写单测,mockk的步骤一样 // 真实对象方法执行时对方法体中的对象方法进行mock和验证 @Test public void testReportLikedVideoRemoveExposure() { BeaconReportService service = mock(BeaconReportService.class); // 使用mock后该对象的属性是null,方法没有实际执行能力 JsonObject jsonObject = getJsonObject("1", "1", "aswq"); mockStatic(Router.class); // reportLikedVideoRemoveExposure()方法调用了静态方法需要提前mock其行为 when(Router.getService(BeaconReportService.class)).thenReturn(service); // 指定mock对象的方法行为 PersonalCenterReport.INSTANCE.reportLikedVideoRemoveExposure("1", any(), "1" ,"aswq"); verify(service) .reportUserExposure(Mockito.eq("liked.remove"), Mockito.eq("1"), eq(jsonObject.toString()), eq(""), eq( "")); // 验证结果 } @NotNull private JsonObject getJsonObject(String num, String rank, String userId) { JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("num", num); jsonObject.addProperty("rank", rank); jsonObject.addProperty("user_id", userId); return jsonObject; } @Test public void testReportLikedVideoRemoveExposure_null() { BeaconReportService service = mock(BeaconReportService.class); JsonObject jsonObject = getJsonObject("1", "1", "aswq"); mockStatic(Router.class); when(Router.getService(BeaconReportService.class)).thenReturn(service); PersonalCenterReport.INSTANCE.reportLikedVideoRemoveExposure("1", any(), "1" ,"aswq"); verify(service) .reportUserExposure(Mockito.eq("liked.remove"), Mockito.eq("1"), eq(jsonObject.toString()), eq(""), eq( "")); } 使用PowerMock时需要注意: @PrepareForTest({Router.class, BeaconReportService.class}) @Rule public PowerMockRule rule = new PowerMockRule(); 被测方法使用kotlin编写,需要把?.的两种情况都覆盖到才会有单测覆盖率 mockk时 [0]: argument: richlike.remove, matcher: eq(richlike.video), result: - [1]: argument: 1, matcher: eq(1), result: + [2]: argument: {"num":"1","rank":"","user_id":""}, matcher: eq({"video_cover":"big","num":"1","label":"0","search_id":"","search_word":""}), result: - [3]: argument: , matcher: eq(), result: + [4]: argument: , matcher: eq(), result: +

根据Matchers文档如下,在打桩阶段有一个原则,一个mock对象的方法,如果其若干个参数中,有一个是通过Matchers提供的,则该方法的所有参数都必须通过Matchers提供。而不能是有的参数通过Matchers提供,有的参数直接给出真实的具体值。

If you are using argument matchers, all arguments have to be provided by matchers. E.g: (example shows verification but the same applies to stubbing):

verify(mock).someMethod(anyInt(), anyString(), eq("third argument"));

//above is correct - eq() is also an argument matcher

verify(mock).someMethod(anyInt(), anyString(), "third argument");

//above is incorrect - exception will be thrown because third argument is given without argument matcher.

Matcher methods like anyObject(), eq() do not return matchers. Internally, they record a matcher on a stack and return a dummy value (usually null).

上述文档中给出的示例,可以使用eq()方法将真实的具体值转换为Matchers提供的值或者在mock行为时参数使用具体的值。

最新回复(0)