4. when语句
4.1. 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();
用途:
用于模拟对象方法,先执行原始方法,再返回期望的值、异常、应答,或调用真实的方法。
4.1.1. 返回期望值
public class ListTest { @Test public void testGet() { int index = 0; Integer expected = 100; List<Integer> mockList = PowerMockito.mock(List.class); PowerMockito.when(mockList.get(index)).thenReturn(expected); Integer actual = mockList.get(index); Assert.assertEquals("返回值不相等", expected, actual); } } |
4.1.2. 返回期望异常
public class ListTest { @Test(expected = IndexOutOfBoundsException.class) public void testGet() { int index = -1; Integer expected = 100; List<Integer> mockList = PowerMockito.mock(List.class); PowerMockito.when(mockList.get(index)).thenThrow(new IndexOutOfBoundsException()); Integer actual = mockList.get(index); Assert.assertEquals("返回值不相等", expected, actual); } } |
4.1.3. 返回期望应答
public class ListTest { @Test public void testGet() { int index = 1; Integer expected = 100; List<Integer> mockList = PowerMockito.mock(List.class); PowerMockito.when(mockList.get(index)).thenAnswer(invocation -> { Integer value = invocation.getArgument(0); return value * 100; }); Integer actual = mockList.get(index); Assert.assertEquals("返回值不相等", expected, actual); } } |
4.1.4. 调用真实方法
public class ListTest { @Test public void testGet() { int index = 0; Integer expected = 100; List<Integer> oldList = new ArrayList<>(); oldList.add(expected); List<Integer> spylist = PowerMockito.spy(oldList); PowerMockito.when(spylist.get(index)).thenCallRealMethod(); Integer actual = spylist.get(index); Assert.assertEquals("返回值不相等", expected, actual); } } |
4.2. 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异常。
4.2.1. 返回期望值
public class ListTest { @Test public void testGet() { int index = 0; Integer expected = 100; List<Integer> mockList = PowerMockito.mock(List.class); PowerMockito.doReturn(expected).when(mockList).get(index); Integer actual = mockList.get(index); Assert.assertEquals("返回值不相等", expected, actual); } } |
4.2.2. 返回期望异常
public class ListTest { @Test(expected = IndexOutOfBoundsException.class) public void testGet() { int index = -1; Integer expected = 100; List<Integer> mockList = PowerMockito.mock(List.class); PowerMockito.doThrow(new IndexOutOfBoundsException()).when(mockList).get(index); Integer actual = mockList.get(index); Assert.assertEquals("返回值不相等", expected, actual); } } |
4.2.3. 返回期望应答
public class ListTest { @Test public void testGet() { int index = 1; Integer expected = 100; List<Integer> mockList = PowerMockito.mock(List.class); PowerMockito.doAnswer(invocation -> { Integer value = invocation.getArgument(0); return value * 100; }).when(mockList).get(index); Integer actual = mockList.get(index); Assert.assertEquals("返回值不相等", expected, actual); } } |
4.2.4. 模拟无返回值
public class ListTest { @Test public void testClear() { List<Integer> mockList = PowerMockito.mock(List.class); PowerMockito.doNothing().when(mockList).clear(); mockList.clear(); Mockito.verify(mockList).clear(); } } |
4.2.5. 调用真实方法
public class ListTest { @Test public void testGet() { int index = 0; Integer expected = 100; List<Integer> oldList = new ArrayList<>(); oldList.add(expected); List<Integer> spylist = PowerMockito.spy(oldList); PowerMockito.doCallRealMethod().when(spylist).get(index); Integer actual = spylist.get(index); Assert.assertEquals("返回值不相等", expected, actual); } } |
4.3. 两种模式的主要区别
两种模式都用于模拟对象方法,在mock实例下使用时,基本上是没有差别的。但是,在spy实例下使用时,when().thenReturn()模式会执行原方法,而doReturn().when()模式不会执行原方法。测试服务类:
@Slf4j @Service public class UserService { public long getUserCount() { log.info("调用获取用户数量方法"); return 0L; } } |
使用when().thenReturn()模式:
@RunWith(PowerMockRunner.class) public class UserServiceTest { @Test public void testGetUserCount() { Long expected = 1000L; UserService userService = PowerMockito.spy(new UserService()); PowerMockito.when(userService.getUserCount()).thenReturn(expected); Long actual = userService.getUserCount(); Assert.assertEquals("返回值不相等", expected, actual); } } |
在测试过程中,将会打印出"调用获取用户数量方法"日志。
使用doReturn().when()模式:
@RunWith(PowerMockRunner.class) public class UserServiceTest { @Test public void testGetUserCount() { Long expected = 1000L; UserService userService = PowerMockito.spy(new UserService()); PowerMockito.doReturn(expected).when(userService).getUserCount(); Long actual = userService.getUserCount(); Assert.assertEquals("返回值不相等", expected, actual); } } |
在测试过程中,不会打印出"调用获取用户数量方法"日志。
4.4. whenNew模拟构造方法
声明:
PowerMockito.whenNew(MockClass.class).withNoArguments().thenReturn(expectedObject);PowerMockito.whenNew(MockClass.class).withArguments(someArgs).thenReturn(expectedObject);
用途:
用于模拟构造方法。
案例:
public final class FileUtils { public static boolean isFile(String 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}),否则模拟方法不生效。
5. 参数匹配器
在执行单元测试时,有时候并不关心传入的参数的值,可以使用参数匹配器。
5.1. 参数匹配器(any)
Mockito提供Mockito.anyInt()、Mockito.anyString、Mockito.any(Class clazz)等来表示任意值。
public class ListTest { @Test public void testGet() { int index = 1; Integer expected = 100; List<Integer> mockList = PowerMockito.mock(List.class); PowerMockito.when(mockList.get(Mockito.anyInt())).thenReturn(expected); Integer actual = mockList.get(index); Assert.assertEquals("返回值不相等", expected, actual); } } |
5.2. 参数匹配器(eq)
当我们使用参数匹配器时,所有参数都应使用匹配器。 如果要为某一参数指定特定值时,就需要使用Mockito.eq()方法。
@RunWith(PowerMockRunner.class) @PrepareForTest({StringUtils.class}) public class StringUtilsTest { @Test public void testStartWith() { String string = "abc"; String prefix = "b"; boolean expected = true; PowerMockito.spy(StringUtils.class); PowerMockito.when(StringUtils.startsWith(Mockito.anyString(), Mockito.eq(prefix))).thenReturn(expected); boolean actual = StringUtils.startsWith(string, prefix); Assert.assertEquals("返回值不相等", expected, actual); } } |
5.3. 附加匹配器
Mockito的AdditionalMatchers类提供了一些很少使用的参数匹配器,我们可以进行参数大于(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()); Integer actual = mockList.get(index); Assert.assertEquals("返回值不相等", expected, actual); } } |
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理