Mockito教程
Mockito是基于Java的模拟框架,可与其他测试框架(例如JUnit和TestNG)结合使用。
它在内部使用Java Reflection API,并允许创建服务对象。
模拟对象返回伪数据,并避免外部依赖关系。
它通过模拟外部依赖项简化了测试的开发,并将模拟应用于要测试的代码。
Mockito教程
对于Mockito教程,我们将使用JUnit 5并创建一些模拟服务。
Mockito Maven依赖关系
要在项目中实现基于Mockito的测试用例,请将以下依赖项添加到项目的pom.xml文件中:
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>2.19.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-junit-jupiter</artifactId> <version>2.19.0</version> <scope>test</scope> </dependency>
注意,对于JUnit 5,mockito-junit-jupiter是必需的,如果您使用的是其他测试框架,例如JUnit 4或者TestNG,则可以删除此依赖项,而仅包括mockito-core依赖项。
Mockito模拟创作
Mockito框架允许我们使用@Mock批注或者static方法mock()创建模拟对象。
Mockito mock()方法
下面的示例演示了mock()方法的用法:
package com.theitroad.mockito;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import com.theitroad.AddService;
import com.theitroad.CalcService;
public class CalcService1Test {
@Test
void testCalc() {
System.out.println("**--- Test testCalc executed ---**");
AddService addService;
CalcService calcService;
addService = Mockito.mock(AddService.class);
calcService = new CalcService(addService);
int num1 = 11;
int num2 = 12;
int expected = 23;
when(addService.add(num1, num2)).thenReturn(expected);
int actual = calcService.calc(num1, num2);
assertEquals(expected, actual);
}
}
在上面的示例中,我们正在测试CalcService。
Mockito.mock()方法用于创建AddService类的模拟对象。
Mockito模拟注解
下面的示例显示@Mock注释的用法。
package com.theitroad.mockito;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import com.theitroad.AddService;
import com.theitroad.CalcService;
public class CalcService2Test {
CalcService calcService;
@Mock
AddService addService;
@BeforeEach
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testCalc() {
System.out.println("**--- Test testCalc executed ---**");
calcService = new CalcService(addService);
int num1 = 11;
int num2 = 12;
int expected = 23;
when(addService.add(num1, num2)).thenReturn(expected);
int actual = calcService.calc(num1, num2);
assertEquals(expected, actual);
}
}
注意,我们需要调用MockitoAnnotations.initMocks(this);来初始化用@ Mock,@ Spy,@ Captor或者@InjectMocks注释的对象。
Mockito行为验证
为了向模拟类when()和thenReturn()函数添加行为。
这意味着当使用(num1,num2)参数为添加方法调用模拟对象(addService)时,它将返回存储在预期变量中的值。
我们的CalcService类如下所示:
public class CalcService {
private AddService addService;
public CalcService(AddService addService) {
this.addService = addService;
}
public int calc(int num1, int num2) {
System.out.println("**--- CalcService calc executed ---**");
return addService.add(num1, num2);
}
}
CalcService依赖于AddService类。
它使用AddService类的add方法执行其操作。
由于我们只想对CalcService类进行单元测试,因此我们必须模拟AddService实例。
AddService如下所示:
public interface AddService {
public int add(int num1, int num2);
}
public class AddServiceImpl implements AddService {
@Override
public int add(int num1, int num2) {
System.out.println("**--- AddServiceImpl add executed ---**");
return num1 + num2;
}
}
Mockito验证互动
Mockito框架跟踪对模拟对象的所有方法调用及其参数。
模拟对象上的Mockitoverify()方法验证使用特定参数调用的方法。
我们还可以指定调用逻辑的数量,例如确切的次数,至少指定的次数,小于指定的次数等。
我们可以将" VerificationModeFactory"用于调用次数逻辑。
Mockito verify()方法检查是否使用正确的参数调用了一个方法。
它不会检查类似assert方法的方法调用的结果。
下面的示例演示了verify()方法的用法:
package com.theitroad.mockito;
import static org.mockito.Mockito.verify;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.mockito.internal.verification.VerificationModeFactory;
public class VerifyInteractionTest {
@Test
public void testMethod() {
@SuppressWarnings("unchecked")
List<String> mockedList = Mockito.mock(List.class);
mockedList.add("first-element");
mockedList.add("second-element");
mockedList.add("third-element");
mockedList.add("third-element");
mockedList.clear();
verify(mockedList).add("first-element");
verify(mockedList).add("second-element");
verify(mockedList, VerificationModeFactory.times(2)).add("third-element");
verify(mockedList).clear();
}
}
Mockito Stub具体程序
使用when()– thenReturn()函数,我们可以对具体/实现类以及集合的单个元素进行存根。
非存根元素将其中包含null。
package com.theitroad.mockito;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class MockSingleElementTest {
@SuppressWarnings("unchecked")
@Test
public void testMethod() {
ArrayList<String> mockedList = mock(ArrayList.class);
when(mockedList.get(0)).thenReturn("first-element");
System.out.println(mockedList.get(0));
assertEquals("first-element", mockedList.get(0));
//"null" gets printed as get(1) is not stubbed
System.out.println(mockedList.get(1));
}
}
Mockito Spy
调用 Spy对象的方法时,除非定义了预定义的行为,否则将调用real方法。
使用 Spy,我们可以通过when()-theReturn()函数定义行为,或者可以调用实际实现。
package com.theitroad.mockito;
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 MockitoSpyTest {
@Test
public void testMethod() {
List<String> list = new ArrayList<>();
List<String> listSpy = spy(list);
listSpy.add("first-element");
System.out.println(listSpy.get(0));
assertEquals("first-element", listSpy.get(0));
when(listSpy.get(0)).thenReturn("second-element");
System.out.println(listSpy.get(0));
assertEquals("second-element", listSpy.get(0));
}
}

