Mockito模拟示例
时间:2020-02-23 14:40:44 来源:igfitidea点击:
Mockito模拟框架提供了模拟类的不同方法。
让我们看一下可以模拟类并显示其行为的不同方法。
Mockito模拟方法
我们可以使用Mockito类的mock()方法创建给定类或者接口的模拟对象。
这是模拟对象的最简单方法。
package com.theitroad.mockito.mock; import java.util.List; import static org.mockito.Mockito.*; import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; public class MockitoMockMethodExample { @SuppressWarnings("unchecked") @Test public void test() { //using Mockito.mock() method List<String> mockList = mock(List.class); when(mockList.size()).thenReturn(5); assertTrue(mockList.size()==5); } }
我们使用JUnit 5与Mockito一起编写测试用例来模拟对象。
Mockito @模拟注解
我们也可以使用@Mock注释来模拟对象。
当我们想在多个地方使用模拟对象时,这很有用,因为我们避免了多次调用mock()方法。
代码变得更具可读性,我们可以指定模拟对象名称,以防出现错误。
使用@Mock注释时,必须确保调用MockitoAnnotations.initMocks(this)
来初始化模拟对象。
我们可以在测试之前执行的测试框架设置方法中执行此操作。
package com.theitroad.mockito.mock; import java.util.List; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; public class MockitoMockAnnotationExample { @Mock List<String> mockList; @BeforeEach public void setup() { //if we don't call below, we will get NullPointerException MockitoAnnotations.initMocks(this); } @SuppressWarnings("unchecked") @Test public void test() { when(mockList.get(0)).thenReturn("theitroad"); assertEquals("theitroad", mockList.get(0)); } }
Mockito @InjectMocks批注
当我们要将一个模拟对象注入另一个模拟对象时,可以使用@InjectMocks批注。
@InjectMock创建类的模拟对象,并将带有注释@Mock的模拟注入到该类中。
package com.theitroad.mockito.mock; import java.util.List; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; public class MockitoInjectMockAnnotationExample { @Mock List<String> mockList; //@InjectMock creates an instance of the class and //injects the mocks that are marked with the annotations @Mock into it. @InjectMocks Fruits mockFruits; @BeforeEach public void setup() { //if we don't call below, we will get NullPointerException MockitoAnnotations.initMocks(this); } @SuppressWarnings("unchecked") @Test public void test() { when(mockList.get(0)).thenReturn("Apple"); when(mockList.size()).thenReturn(1); assertEquals("Apple", mockList.get(0)); assertEquals(1, mockList.size()); //mockFruits names is using mockList, below asserts confirm it assertEquals("Apple", mockFruits.getNames().get(0)); assertEquals(1, mockFruits.getNames().size()); mockList.add(1, "Mango"); //below will print null because mockList.get(1) is not stubbed System.out.println(mockList.get(1)); } } class Fruits{ private List<String> names; public List<String> getNames() { return names; } public void setNames(List<String> names) { this.names = names; } }
Mockito spy()进行部分模拟
如果我们只想模拟特定的行为,并调用未受干扰行为的真实方法,则可以使用Mockito spy()方法创建一个间谍对象。
package com.theitroad.mockito.mock; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.Test; public class MockitoSpyMethodExample { @Test public void test() { List<String> list = new ArrayList<>(); List<String> spyOnList = spy(list); when(spyOnList.size()).thenReturn(10); assertEquals(10, spyOnList.size()); //calling real methods since below methods are not stubbed spyOnList.add("hyman"); spyOnList.add("Meghna"); assertEquals("hyman", spyOnList.get(0)); assertEquals("Meghna", spyOnList.get(1)); } }
Mockito @Spy注释
我们可以使用@Spy注释监视对象。
让我们看一个简单的例子。
package com.theitroad.mockito.mock; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.MockitoAnnotations; import org.mockito.Spy; public class MockitoSpyAnnotationExample { @Spy Utils mockUtils; @BeforeEach public void setup() { MockitoAnnotations.initMocks(this); } @Test public void test() { when(mockUtils.process(1, 1)).thenReturn(5); //mocked method assertEquals(5, mockUtils.process(1, 1)); //real method called since it's not stubbed assertEquals(20, mockUtils.process(19, 1)); } } class Utils{ public int process(int x, int y) { System.out.println("Input Params = "+x+","+y); return x+y; } }
请注意,@ Spy批注会尝试调用no-args构造函数以初始化模拟对象。
如果您的程序没有该程序,则会收到以下错误。
org.mockito.exceptions.base.MockitoException: Unable to initialize @Spy annotated field 'mockUtils'. Please ensure that the type 'Utils' has a no-arg constructor. at com.theitroad.mockito.mock.MockitoSpyAnnotationExample.setup(MockitoSpyAnnotationExample.java:18)
另外,请注意,Mockito无法实例化内部类,局部类,抽象类和接口。
因此,最好提供一个实例进行监视。
否则,实际的方法可能不会被调用并被静默忽略。
例如,如果您指定一个间谍对象,如下所示:
@Spy List<String> spyList;
您会注意到,当您调用add()或者get()方法时,不会调用实际方法。
如果您指定如下所示的间谍对象,那么一切都会正常进行。
@Spy List<String> spyList = new ArrayList<>();