Qouson's blog Qouson's blog
首页
  • Java 基础

    • 基础
    • String
  • Java 中级

    • 网络编程
  • Java 高级

    • JVM
    • 多线程
  • Spring
  • SpringMVC
  • SpringBoot
  • MySQL
  • Redis
  • MQ
  • ZooKeeper
  • git
  • linux
  • 设计模式
  • 数据结构与算法
  • 计算机基础
  • Java相关框架
  • 分布式
  • DDD领域驱动设计
  • 系统设计
  • 杂乱无章
Java知识图谱
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

qouson

Java界的小学生
首页
  • Java 基础

    • 基础
    • String
  • Java 中级

    • 网络编程
  • Java 高级

    • JVM
    • 多线程
  • Spring
  • SpringMVC
  • SpringBoot
  • MySQL
  • Redis
  • MQ
  • ZooKeeper
  • git
  • linux
  • 设计模式
  • 数据结构与算法
  • 计算机基础
  • Java相关框架
  • 分布式
  • DDD领域驱动设计
  • 系统设计
  • 杂乱无章
Java知识图谱
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • git

  • linux

  • 设计模式

  • 数据结构与算法

  • 计算机基础

  • Java相关框架

  • 分布式

  • DDD领域驱动设计

  • 系统设计

  • DevOps

  • python

  • 杂乱无章

    • 杂乱无章
      • 更新2024-12-26
        • 流程图测试
      • 更新2024-12-26
      • 更新2025-01-02
      • 更新2025-01-03
        • verify:验证是确认在模拟过程中,被测试方法是否按预期方式与其任何依赖方法进行了交互。
        • PowerMockito的mock和spy的区别:
        • 单元测试断言
        • 单元测试必须断言
        • 单元测试断言的方式
  • 更多
  • 杂乱无章
qouson
2024-12-25
目录

杂乱无章

# 杂乱无章

# 更新2024-12-26

# 流程图测试

graph TD
  A(开始) -- just test --> B{是否符合}
  B -- yes --> C
  B -- no --> D
  C --> E(结束)
  D --> E(结束)
1
2
3
4
5
6
https://wx.zsxq.com/group/51121241882444/topic/4848544415524848

覆盖率
单元测试
集成测试
1
2
3
4
5

# 更新2024-12-26

一般用Junit+Mockito+PowerMockito

T PowerMockito.mock(Class clazz):
用途:用于模拟指定类的对象实例。
当模拟非final类(接口,普通类,虚基类)的非final方法时,不必使用@RunWith和@PrepareForTest注解。
当模拟final类或final方法时,必须使用@RunWith(PowerMockRunner.class)和@PrepareForTest({StringUtils.class})注解

PowerMockito.mockStatic(Class clazz);
用途:用于模拟类的静态方法,必须使用@RunWith(PowerMockRunner.class)和@PrepareForTest({StringUtils.class})注解

一个简单的例子:
public class ListTest{
    @Test
    public void testSize(){
        Integer expected = 100;
        List list = PowerMockito.mock(List.class);
        PowerMockito.when(list.size()).thenReturn(expected);
        Integer actual = list.size();
        Assert.assertEquals("返回值不相等", expected, actual);    
     }
}

mock语句
mock方法
声明:T PowerMockito.mock(Class clazz):用途:用于模拟指定类的对象实例。
当模拟非final类(接口,普通类,虚基类)的非final方法时,不必使用@RunWith和@PrepareForTest注解。)
当模拟final类或final方法时,必须使用@RunWith(PowerMockRunner.class)和@PrepareForTest({StringUtils.class})注解

模拟非final类普通方法
public class Rectangle implements Shape{
    private double width;
    private double height;
    @Override
    public double getArea(){
        return width * height;
    }
}
public class RectangleTest{
    @Test
    public void testGetArea(){
        double expectArea = 100.0D;
        Rectangle rectangle = PowerMockito.mock(Rectangle.class);
        PowerMockito.when(rectangle.getArea()).thenReturn(expectArea);)
        double actual = rectangle.getArea();
        Assert.assertEquals("返回值不相等", expectArea, actual);
    }
}

模拟final类或final方法
需要使用@RundWith(PowderMockRunner.class)和@PrepareForTest({Circle.class})注解
public final class Circle{
    private double radius;
    public double getArea(){
        return Math.PI * Math.pow(radius, 2);
    }
}
@RunWith(PowerMockRunner.class)
@PrepareForTest({Circle.class})
public class CircleTest{
    @Test
    public void testGetArea(){
        double expectArea = 100.0D;
        Circle circle = PowerMockito.mock(Circle.class);
        PowerMockito.when(circle.getArea()).thenReturn(expectArea);
        double actual = circle.getArea();
        Assert.assertEquals("返回值不相等", expectArea, actual);
    }
}

mockStatic方法
PowerMockito.mockStatic(Class clazz):用途:用于模拟类的静态方法,必须使用@RunWith(PowerMockRunner.class)和@PrepareForTest({StringUtils.class})注解
@RunWith(PowerMockRunner.class)
@PrepareForTest({StringUtils.class})
public class StringUtilsTest{
    @Test
    public void testIsEmpty(){
        String string = "abc";
        boolean expected = true;
        PowerMockito.when(StringUtils.class);
        PowerMockito.when(StringUtils.isEmpty(string)).thenReturn(expected);
        boolean actual = StringUtils.isEmpty(string); // 这里调用时,就会发现是返回的mock数据
        Assert.assertEquals("返回值不相等", expected, actual);
    }
}


spy语句:
如果一个对象,我们只希望模拟它的部分方法,而希望其他方法跟原来一样,可以使用PowerMockito.spy方法替代PowerMockito.mock方法。
通过when设置过的方法,调用的是模拟方法,没有通过when语句的调用的是原来的方法
powerMock又两种使用,一种是非注解,一种是注解注入的。
Spy类(非注解):
PowerMockito.spy(StringUtils.class)
PowerMockito.when(StringUtils.isEmpty(string)).thenReturn(!expected)
例子:
spy对象(非注解):
声明:T PowerMockito.spy(T object):用途:用于模拟对象的部分方法,如UserService类要测试isNotSuperUser方法,但是要mock掉isSupperUser这个方法,就需要对这个类加个spy,注解为@RunWith(PowderMockRunner.class)
案例:
public class UserService{
    private Long superUserId;
    public boolean isNotSuperUser(Long userId){
        return !isSuperUser(userId);
    }
    public boolean isSuperUser(Long userId){
        return Objects.equals(userId, superUserId);
    }
}

@RunWith(PowerMockRunner.class)
public class UserServiceTest{
    @Test
    public void testIsNotSuperUser(){
        Long userId = 1L;
        boolean expected = false;
        UserService userService = PowerMockito.spy(UserService.class);
        PowerMockito.when(userService.isSuperUser(userId)).thenReturn(!expected);
        boolean actual = userService.isNotSuperUser(userId);
        Assert.assertEquals("返回值不相等", expected, actual);
    }
}


注解:使用InjectMocks注解注入的方式,使用@Spy
@RundWith(PowerMockRunner.class)
public class UserServiceTest{
    @Spy
    @InjectMocks
    private UserService userServiceSpy = new UserService();
    @Test
    public void testIsNotSuperUser(){
        Long userId = 1L;
        boolean expected = false;
        // 不要使用这种方法是,会先调用方法再mock
        // PowerMockito.when(userServiceSpy).isSuperUser(userId);
        // 这种方式就不会先调用方法
        // 直接使用userId是强匹配,使用any()是所有参数都匹配
        doReturn(!expected).when(userServiceSpy).isSuperUser(userId);
        boolean actual = userService.isNotSuperUser(userId);
        Assert.assertEquals("返回值不相等", expected, actual);
    }
}


when语句
when().thenReturn()
声明:
PowerMockito.when(mockObject.someMethod(someArgs)).thenReturn(expectedValue);
PowerMockito.when(mockObject.someMethod(someArgs)).thenThrow(expectedThrowable);
PowerMockito.when(mockObject.someMethod(someArgs)).thenAnswer(expectedAnswer);
PowerMockito.when(mockObject.someMethod(someArgs)).thenCallRealMethod();
用途:用于模拟对象方法,先执行原始放啊,再返回期望的值,异常,应答,或调用真实方法。

doReturn().when()
模式
声明:
Powermockito.doReturn(expectedValue).when(mockObject).someMethod(someArgs);
PowerMockito.doThrow(expectedThrowable).when(mockObject).someMethod(someArgs);
PowerMockito.doAnswer(expectedAnswer).when(mockObject).someMethod(someArgs);
PowerMockito.doNothing().when(mockObject).someMethod(someArgs);
PowerMockito.doCallRealMethod().when(mockObject).someMethod(someArgs);
用途:用于模拟对象方法,直接返回期望值的值,异常,应答,或调用真实方法。无需执行原始方法。
注意:千万不要使用以下语法:
PowerMockito.doReturn(expectedValue).when(mockObject.someMethod(someArgs));
PowerMockito.doThrow(expectedThrowable).when(mockObject.someMethod(someArgs));
PowerMockito.doAnswer(expectedAnswer).when(mockObject.someMethod(someArgs));
PowerMockito.doNothing().when(mockObject.someMethod(someArgs));
PowerMockito.doCallRealMethod().when(mockObject.someMethod(someArgs));
虽然不会出现编译错误,但是在执行时会抛出UnfinishedStubbingException异常。

两种模式的主要区别:
两种模式都用于模拟对象方法,在mock实例下使用时,基本上没有差别。但是在spy实例下使用,when().thenReturn()会先执行原方法,而doReturn().when()不会执行原方法。


whenNew模拟构造方法
声明:
PowerMockito.whenNew(MockClass.class).withNoArguments().thenReturn(expectedObject);
PowerMockito.whenNew(MockClass.class).withArguments(someArgs).thenReturn(expectedObject);

用途:用于模拟构造方法。案例:
public final class FileUtils{
    public static boolean isFile(Sting fileName){
        return new File(fileName).isFile();
    }
}
@RunWith(PowerMockRunner.class)
@PrepareForTest(FileUtils.class)
public class FileUtilsTest{
    @Test
    public void testIsFile() throws Exception{
        String fileName = "test.txt";
        File file = PowerMockito.mock(File.class);
        PowerMockito.whenNew(File.class).withArguments(fileName).thenReturn(file);
        PowerMockito.when(file.isFile()).thenReturn(true);
        Assert.assertTrue("返回值为假",FileUtils.isFile(fileName));
    }
}
注意:需要加上注解@PrepareForTest(FileUtils.class),否则模拟方法不生效。


参数匹配器:
在执行单元测试时,有时候不关心传入的参数的值,可以使用参数匹配器。
注意:你能具体到指定类型如anyString,anyInt,就不用any()。null值必须显式用null,或eq(null)来匹配

参数匹配器(any)
Mockito提供Mockito.anyInt(),Mockito.anyString,Mockito.any(Class clazz)来表示任何值。
public class ListTest{
    @Test
    public void testGet(){
        int index = 1;
        Integer expcected = 100;
        List<Integer> mockList = PowerMockito.mock(List.class);
        PowerMockito.when(mockList.get(Mockito.anyInt())).thenReturn(expcected);
        Integer actual = mockList.get(index);
        Assert.assertEquals("返回值不相等", expcected, actual);
    }
}


参数匹配器(eq)
当我们使用参数匹配器时,所有参数都应使用匹配器。如果要为某一参数指定特定值时,就需要使用Mockito.eq()方法。
@Runwith(PowerMockRunner.class)
@PrepareForTest(StringUtils.class)
public class StringUtilsTest{
    @Test
    public void testStartWith(){
        String string = "abc";
        String perfix = "b";
        boolean expected = true;
        PowerMockito.spy(StringUtils.class);
        PowerMockito.when(StringUtils.startWith(Mockito.anyString(),Mockito.eq(prefix))).thenReturn(expected);
        boolean actual = StringUtils.startsWith(string,perfix);
        Assert.assertEquals("返回值不相等", expected, actual);
    }
}


附加匹配器
Mockito的AdditionalMathchers类提供了一些很少使用的参数匹配器,我们可以进行参数大于(gt)、小于(lt)、大于等于(geq)、小于等于(leq)等比较操作,也可以进行参数与(and)、或(or)、非(not)等逻辑操作。
public class ListTest{
    @Test
    public void testGet(){
        int index = 1;
        Integer expected = 100;
        List<Integer> mockList =PowerMockito.mock(List.class);
        PowerMockito.when(mockList.get(AdditionalMatchers.geq(0))).thenReturn(expected);
        PowerMockito.when(mockList.get(AdditionalMatchers.lt(0))).thenThrow(new IndexOutOfBoundsException());
        Intger actual = mockList.get(index);
        Assert.assertEquals("返回值不相等", expected, actual);
    }
}


verify语句
验证是确认在模拟过程中,被测试方法是否已按预期方式与其任何依赖方法进行了交互。
格式:
Mockito.verify(mockObject[,times(int)]).someMethod(someArgs);
用途:
用于模拟对象方法,直接返回预期的值,异常,应答,或调用真实方法。
案例:
验证调用方法
public classLi身体Test{
    @Test
    public void testGet(){
        List<Iteger> mockList= PowerMockito.mock(List.class);
        PowerMockito.doNothing().when(mockList).clear();
        mockList.clear();
        Mockito.verify(mockList).clear();
    }
}

public class ListTest{
    @Test
    public void testGet(){
        List<Integer> mockList = PowerMockito.mock(List.class);
        PowerMockito.doNothing().when(mockList).clear();
        mockList.clear();
        Mockito.verify(mockList,Mockito.times(1)).clear();
    }
}
除times外,Mockito还支持atLeastOne,atLeast,only,atMostOnce,atMost等次数验证器


验证调用顺序
public class ListTest{
    @Test
    public void testAdd(){
        List<Integer> mockList = PowerMockito.mock(List.class);
        PowerMockito.doReturn(true).when(mockList).add(Mockito.anyInt());
        mockedList.add(1);
        mockedList.add(2);
        mockedList.add(3);
        InOrder inOrder = Mockito.inOrder(mockList);
        inOrder.verify(mockList).add(1);
        inOrder.verify(mockList).add(2);
        inOrder.verify(mockList).add(3);
    }
}


验证调用参数
用于断言void方法,没有返回结果,可以断言内部调用的请求参数
public class ListTest{
    @Test
    public void testArgumentCaptor(){
        Integer[] expecteds = new Integer[]{1,2,3};
        List<Integer> mockedList = PowerMockito.mock(List.class);
        PowerMockito.doReturn(true).when(mockedList).add(Mockito.anyInt());
        for(Integer expected : expecteds){
            mockedList.add(expected);
        }
        ArgumentCaptor<Integer> argumentCaptor = ArgumentCaptor.forClass(Integer.class);
        Mockito.verify(mockedList,Mockito.times(3)).add(argumentCaptor.capture());
        Integer[] actuals = argumentCaptor.getAllValues().toArray(new Integer[0]);
        Assert.assertArrayEquals("参数不相等",expecteds,actuals);
    }
}


确保验证完毕
Mockito提供Mockito.verifyNoMoreInteractions方法,在所有验证方法之后可以使用此方法,以确保所有调用都得到验证。如果模拟对象上存在未验证的调用,将会抛出NoInteractionsWanted异常。
public class ListTest{
    @Test
    public void testVerifyNoMoreInteractions(){
        List<Integer> mockedList = PowerMockito.mock(List.class);
        Mockito.verifyNoMoreInteractions(mockedList);//执行正常呢
        mockedList.isEmpty();
        Mockito.verifyNoMoreInteractions(mockedList);//抛出异常
    }
}
备注:Mockito.verifyZeroInteractions(mockedList)与Mockito.verifyNoMoreInteractions(mockedList)效果相同,但目前已经被废弃。


验证静态方法
Mockito没有静态方法的验证方法,但是PowerMockito提供了静态方法的验证方法。注意:@RunWith(PowerMockRunner.class)和@PrepareForTest(StaticClass.class)
@Runwith(PowerMockRunner.class)
@PrepareForTest(StringUtils.class)
public class StringUtilsTest{
    @Test
    public void testVerifyStatic(){
        PowerMockito.spy(StringUtils.class);
        String expected = "abc";
        StringUtils.isEmpty(expected);
        PowerMockito.verifyStatic(StringUtils.class);
        ArgumentCaptor<String> argumentCaptor = ArgumentCaptor.forClass(String.class);
        StringUtils.isEmpty(argumentCaptor.capture());
        Assert.assertEquals("参数不相等",expected,argumentCaptor.getValue());
    }
}


私有属性
ReflectionTestUtils.setField方法
在用原生JUnit进行单元测试时,我们一般采用ReflectionTestUtils.setField方法来设置私有属性。
@Service
public class UserService{
    @Value("${system.userLimit}")
    private Long userLimit;
    public Long getUserLimit(){
        return userLimit;
    }
}
public class UserServiceTest{
    @Autowired
    private UserService userService;
    @Test
    public void testGetUserLimit(){
        Long expected = 1000L;
        ReflectionTestUtils.setField(userService,"userLimit",expected);
        Long actual = userService.getUserLimit();
        Assert.assertEquals("返回值不相等",expected,actual);
    }
}
注意:在测试类中,UserService实例是通过@Autowired注解加载的,如果该实例已经被动态代理,ReflectionTestUtils。setField方法设置的是代理实例,从而导致设置不生效。


Whitebox.setInternalState方法
现在使用PowerMock进行单元测试时,可以采用Whitebox.setInternalState方法设置私有属性值。注意:@RunWith(PowerMockRunner.class)
@Service
public class UserService{
    @Value("${system.userLimit}")
    private Long userLimit;
    public Long getUserLimit(){
        return userLimit;
    }
}
@RunWith(PowerMockRunner.class)
public class UserServiceTest{
    @InjectMocks
    private UserService userService;
    @Test
    public void testGetUserLimit(){
        Long expected = 1000L;
        Whitebox.setInternalState(userService,"userLimit",expected);
        Long actual = userService.getUserLimit();
        Assert.assertEquals("返回值不相等",expected,actual);
    }
}
注意:需要加上注解@RunWith(PowerMockRunner.class)


私有方法
模拟私有方法
Mockito没有私有方法的mock方法,但是PowerMockito提供了私有方法的模拟方法。注意:@RunWith(PowerMockRunner.class)和@PrepareForTest(UserService.class),mock私有方法入参不要使用匹配器,可能会导致匹配失败。
通过when实现
public class UserService{
    private Long superUserId;
    public boolean isNotSupperUser(Long userId){
        return !isSupperUser(userId);
    }
    private boolean isSuppperUser(Long userId){
        return Objects.equals(userId,superUserId);
    }
}
@RunWith(PowerMockRunner.class)
@PrepareForTest(UserService.class)
public class UserServiceTest{
    @Test
    public void testIsNotSupperUser() throws Exception{
        Long userId = 1L;
        boolean expected = false;
        UserService userService = PowerMockito.spy(new UserService());
        PowerMockito.when(userService, "isSuppperUser", userId).thenReturn(expected);
        boolean actual = userService.isNotSupperUser(userId);
        Assert.assertEquals("返回值不相等",expected,actual);
    }
}


通过stub实现
通过模拟方法stub(存根),也可以实现模拟私有方法。但是,只能模拟整个方法的返回值,不能模拟指定参数的返回值。
@RunWith(PowerMockRunner.class)
@PrepareForTest(UserService.class)
public class UserServiceTest{
    @Test
    public void testIsNotSupperUser() throws Exception{
        Long userId = 1L;
        boolean expected = false;
        UserService userService = PowerMockito.spy(new UserService());
        PowerMockito.stub(PowerMockito.method(UserService.class,"isSuppperUser")).toReturn(expected);
        boolean actual = userService.isNotSupperUser(userId);
        Assert.assertEquals("返回值不相等",expected,actual);
    }
}


测试私有方法
@RunWith(PowerMockRunner.class)
public class UserServiceTest{
    @Test
    public void testIsSupperUser() throws Exception{
        Long userId = 1L;
        boolean expected = false;
        UserService userService = new UserService();
        Method method = PowerMockito.method(UserService.class,"isSuppperUser", Long.class);
        Object actual = method.invoke(userService,userId);
        Assert.assertEquals("返回值不相等",expected,actual);
    }
}


验证私有方法
@RunWith(PowerMockRunner.class)
@PrepareForTest(UserService.class)
public class UserServiceTest{
    @Test
    public void testIsNotSupperUser() throws Exception{
        Long userId = 1L;
        boolean expected = false;
        UserService userService = PowerMockito.spy(new UserService());
        PowerMockito.when(userService, "isSuppperUser", userId).thenReturn(expected);
        boolean actual = userService.isNotSupperUser(userId);
        PowerMockito.verifyPrivate(userService).invoke("isSuppperUser",userId);
        Assert.assertEquals("返回值不相等",expected,actual);
    }
}
这里,也可以用Method那套方法进行模拟和验证方法。


主要注解:
PowerMock为了更好地支持SpringMVC/SpringBoot项目,提供了一系列注解,大大简化测试代码。

@RunWith注解,指定JUnit使用PowerMock框架中的单元测试运行器。

@PrepareForTest注解,指定需要模拟final类,final方法或静态方法。如果需要指定多个类,在{}中添加多个类并用逗号隔开。

@Mock注解,创建了一个全部Mock的实例,所有属性和方法全被置空(0或null)。通常可以加上@Mock(lenient = true)防止mock未使用而报错。

@Spy注解,创建了一个没有Mock的实例,所有成员方法都会按照原方法逻辑执行,知道被Mock返回某个具体的值为止。注意:@Spy注解的变量需要被初始化,否则执行时抛出异常。

@InjectMocks注解,创建一个实例,这个实例可以调用真实代码,其余用@Mock或@Spy注解创建的实例将被注入到这个实例中。

@Captor注解,该注解在字段级别创建参数捕获器。但是,在测试方法启动前必须调用MockitoAnnotations.openMocks(this)进行初始化。

@PowerMockIgnore注解,为了解决使用PowerMock后,提示ClassLoader错误。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493

# 更新2025-01-02

spy:模拟对象的某些方法
用spy指定getServerIp方法的返回值
@InjectMocks
EmpFlowExecuteWork empFlowExecuteWork = new EmpFlowExecuteWork();
String serverIp = "192.168.1.1";
EmpFlowExecuteWork spy = PowerMockito.spy(empFlowExecuteWork);
PowerMockito.doReturn(serverIp).when(spy,"getServerIp");
String serverIpResult = spy.getServerIp();
Assert.assertEquals("参数不相等",serverIp,serverIpResult);

mockStatic:模拟静态方法
@RunWith(PowerMockRunner.class)
@PrepareForTest(EMPLog.class)
PowderMockito.mockStatic(EMPLog.class);
EMPLog.info("test");
PowerMockito.verifyStatic(EMPLog.class);
EMPLog.info("test");

whenNew模拟构造方法
@RunWith(PowerMockRunner.class)
@PrepareForTest(File.class)
PowderMockito.whenNew(File.class).withArguments("test").thenReturn(file);

调用私有方法
AlipayDetails AlipayDetails = new AlipayDetails();
Method method = PowerMockito.method(AlipayDetails.class,"getAlipayDetails",String.class);
method.invoke(AlipayDetails,"test");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 更新2025-01-03

# verify:验证是确认在模拟过程中,被测试方法是否按预期方式与其任何依赖方法进行了交互。

# PowerMockito的mock和spy的区别:

mock:模拟对象,模拟对象调用的方法,返回模拟值。
spy:包装一个已经存在的对象,先调用真实方法,当方法调用未定义才再调用模拟方法。
1
2

# 单元测试断言

# 单元测试必须断言

# 单元测试断言的方式

1. Junit自带断言,用于判断两个值是否相等
1

assertEquals(expected,actual)

2. Junit自带断言,用于判断数组容器是否相等
1

assertArrayEquals(expected,actual)

3. Junit自带断言,用于判断Boolean是否为true
1

assertTrue(actual)

4. Junit自带断言,用于判断Boolean是否为false
1

assertFalse(actual)

5. Junit自带断言,用于判断是同一个对象
1

assertSame(expected,actual)

6. Junit自带断言,用于判断不是同一个对象
1

assertNotSame(expected,actual)

7. Junit自带断言,用于判断对象是否为null
1

assertNull(actual)

8. Junit自带断言,用于判断对象是否不为null
1

assertNotNull(actual)

9. Junit自带断言,用于判断参数值是否匹配规则
1

assertThat(actual,matcher)

10. Junit自带断言,天狼星框架
通过WriteLogUtil类中的printAssertionErrorAndException来统一输出错误断言信息和异常信息
1
2

11. expect,expectMessage
通过Junit中ExpectedException类对象,来断言期望的异常类对象和详细的异常信息
@Rule
public ExpectedException exRule = ExpectedException.none();
// 断言是否为BizExceptioin
exRule.expect(BizException.class);
// 断言返回具体的异常信息
exRule.expectMessage("");

12. verify
Mockito中检查是否发生了某些行为
Mockito.verify(mockObj, mock.times(1)).method(any());
1
2
3
4
5
6
7
8
9
10
11
12
13

// 被测方法,Controller层syncOrderStatus方法 public void syncOrderStatus(){ // 验证syncOrderStatus的调用次数 orderStatusSyncService.syncOrderStatus(); } // 被测方法 @Test public void unionOrderStatusSyncTest(){ PowderMockito.doNothing().when(orderStatusSyncService).syncOrderStatus(); // 获取mockObj OrderStatusSyncService orderStatusSyncService = PowderMockito.mock(OrderStatusSyncService.class); orderStatusSyncController.syncOrderStatus(); // orderStatusSyncService为mock对象,Mockito.times(1)为调用次数;syncOrderStatus为mock对象中调用的方法 Mockito.verify(orderStatusSyncService, Mockito.times(1)).syncOrderStatus(); }


13. andExpected
MockMvc单元测试
- mockMvc.perform 执行一个请求
- MockMvcRequestBuilders.get 创建一个请求
- ResultActions.param添加请求传值
- ResultActions.accept(MediaType.APPLICATION_JSON)设置返回类型
- ResultActions.andExpect添加执行完成后的断言
- ResultActions.andDo添加一个结果处理器,表示要对结果做点什么事情
- ResultActions.andReturn执行结果
1
2
3
4
5
6
7
8
9
10

MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders .get("/login") .accept(MediaType.APPLICATION_JSON) .param("name","") .andExpect(status().isOk()) .andExpect(jsonPath("$.status").value(subMerchantAddResultVO.getStatus())) .andDo(logging.info("")) .andReturn());

例如: // 被测类 public class HelloController { @RequestMapping("/hello") public String hello(){ return "hello"; } }

// 测试方法 private MockMvc mvc = MockMvcBuilders.standaloneSetup(new HelloController()).build();

@Test public void helloTest() throws Exception { mvc.perform(MockMvcRequestBuilders .get("/hello") .param("hello") .accept(MediaType.APPLICATION_JSON)) .andExpect(content().string("hello")) }


14. verifyStatic,PowerMockito中用来验证Mock对象中静态方法是否执行的行为。
15. verifyPrivate,PowerMockito中用来验证Mock对象中私有方法是否执行的行为。
1
2
3

PowderMockito.verifyPrivate(mockObj).invoke(method,argument)

16. public接口无返回值如何断言
1
  1. 断言方法执行次数 Mockito.verify(mockObj, Mockito.times(1)).method(argument);
 
17. 捕获mock方法的调用参数,并进行断言,
1
2

@Test public void argumentTest(){ List list = mock(List.class); List list1 = mock(List.class); List list2 = mock(List.class); list.add("0"); list2.add("1"); list2.add("2");

// 调用0次,无需断言参数,可直接断言次数
ArgumentCaptor<String> argumentCaptor = ArgumentCaptor.forClass(String.class);
verify(list3,times(0)).add(argumentCaptor.capture());

// 调用一次,断言参数
ArgumentCaptor<String> argumentCaptor1 = ArgumentCaptor.forClass(String.class);
verify(list).add(argumentCaptor1.capture());
assertEquals("0",argumentCaptor1.getValue());

// 调用多次,断言参数
ArgumentCaptor<String> argumentCaptor2 = ArgumentCaptor.forClass(String.class);
verify(list2,times(2)).add(argumentCaptor2.capture());
List listActual = argumentCaptor2.getAllValues();
assertEquals("1",listActual.get(0));
assertEquals("2",listActual.get(1));

}



public long getTimestamp(String dateString) throws ParseException {
    if(StringUtils.isNotBlank(dateString)){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.parse(dateString).getTime();
    }
    return 0;
}
1
2
3
4
5
6
7
8
9
编辑 (opens new window)
上次更新: 2025/01/20, 17:53:43
python

← python

最近更新
01
基础-大彬
11-14
02
集合-大彬
11-14
03
MySQL_xiaolingcode
11-14
更多文章>
Theme by Vdoing | Copyright © 2023-2025 qouson
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式