01使用Mockito

普通java项目

第一步:导入依赖的包

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-all</artifactId>
    <version>1.9.0</version>
    <scope>test</scope>
</dependency>

 

第二步:编写测试类

@RunWith(MockitoJUnitRunner.class)
Mockito是通过JUnit运行器运行的,它替我们创建所有必需的模拟对象,并将其注入包含测试的类。
要让一个类能够使用Mockito注解,必须使用MockitoJUnitRunner运行。
@RunWith(MockitoJUnitRunner.class)
public class MockitoTest{}

 

第三步:注入需要Mock的待测试对象
@InjectMocks
测试类中,需要使用@InjectMocks标注受测类,以告诉Mockito应将模拟对象注入哪个类
注意,Mockito会调用对象的无参构造方法创建后注入
@InjectMocks
UserService userService;

 

第四步:注入需要Mock的对象
@Mock
指定要将@InjectMocks标注的类中哪些方法或对象替换为模拟对象

 

第五步:Mock的demo

public class Student {
    private String name;
    public Student(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}

public class StudentMapper {
    public Student getStudent(){
        return null;
    }
}

public class StudentService {
    private StudentMapper studentMapper;
    public Student getStudent(){
        return studentMapper.getStudent();
    }
}

@RunWith(MockitoJUnitRunner.class)
public class MockitoTest{
    @InjectMocks
    StudentService studentService;

    @Mock
    StudentMapper studentMapper;

    @Test
    public void mockTest(){
        Student stu = new Student("zwy");
        doReturn(stu).when(studentMapper).getStudent();
        System.out.println(studentMapper.getStudent());
        System.out.println(studentService.getStudent());
    }

    @Test
    public void spyTest(){
        String exceptStuName = "yly";
        Student stu = new Student("zwy");
//        doReturn(exceptStuName).when(stu).getName();//异常
        System.out.println(stu.getName());
        Student spyStudent = spy(stu);
        doReturn(exceptStuName).when(spyStudent).getName();//正常
        System.out.println(spyStudent.getName());

    }
}

 

结论
1.被 @InjectMocks 标注的对象不能直接mock而被 @Mock 标注的对象可以
2.被 spy(T) 方法包装后的对象可以mock他的行为

@Spy和@Mock的区别?
1.默认行为的不同
对于未指定mock的方法,spy默认会调用真实的方法,有返回值的返回真实的返回值,
而mock默认不执行,有返回值的,默认返回null
2.都不会自动装配到其他容器Bean

 

SpringBoot项目

说明:spring-boot-test模块中默认集成了mockito所以我们可以直接使用。

 

第一步:编写测试类

import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest
@RunWith(SpringRunner.class)
public class ApplicationTest {

    @MockBean
    StudentMapper studentMapper;
    
    @SpyBean
    StudentService studentService;
    
}

 

@SpyBean和@MockBean的区别?
1.默认行为不同
@MockBean属于替换容器的Bean,没有mock的行为返回null
@SpyBean监听容器Bean的行为,没有mock的行为调用Bean的真实方法
2.都会自动装配

 

 

通用

如何 Mock 对象的行为?
// mock返回对象
Mockito.when(methodCall).thenReturn(value)
Mockito.doReturn(toBeReturned).when(mock).[method]
// mock返回void
Mockito.doNothing().when(mock).[method]
// mock抛出异常
Mockito.doThrow(Exception.when(mock).[method]


如何匹配任何参数返回Mock的对象?
Mockito.anyInt()任何int值,Mockito.any(XXX.class)任何XXX类型的值
Mockito.any();
Mockito.any(Student.class);
Mockito.anyString();

如何根据参数的不同判断只有符合条件的参数返回mock的值?
argThat(ArgumentMatcher<T> matcher)
创建参数的Matcher
Matcher<String> argumentMatcher = new ArgumentMatcher<String>() {
@Override
public boolean matches(Object o) {
if("Joe".equals(o)){
return true;
}
return false;
}
};
Mockito.argThat(argumentMatcher);

如何根据参数的不同返回不同的值?
Mockito.doAnswer(new CustomAnswer()).when(mock).get(Mockito.anyInt());
public class CustomAnswer implements Answer<String> {
public String answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
Integer num = (Integer) args[0];
if (num > 3) {
return "大于三";
} else {
return "小于三";
}
}
}

官方文档
https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html

 

上一篇:73递增子序列(491)


下一篇:0001 最大公约数