Mockito详解(二)Mockito中的语法和示例

本文详细介绍了Mockito库中的关键概念和用法,包括@Mock和@InjectMocks注解的使用,模拟(Subbing)与断言(Assert)的语法,Spy对象的创建及其与Mock的区别,以及Matcher参数的运用,如isA(), any(), eq()等。" 131215194,18852486,Python实现关键特征因子抽取,"['Python', '机器学习', '数据处理', '自然语言处理', '特征提取']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、@Mock和@InjectMocks

@InjectMocks 通常加在被测试对象上。 该对象不会被mock,会创建真实的对象,把其他Mock的对象注入被测试对象上
@Mock 标注的对象对生成一个假的对象

二、Subbing和Assert

对于以下语法请参照例子:
when…thenReturn,when…thenThrow, when…thenAnswer, when…thenCallRealMethod
doReturn, doThrow, doNothing
Assert:assertEquals, assertThrows

@RunWith(MockitoJUnitRunner.class)
public class SubbingTest {

    @Mock
    private List<String> list;

    @Test
    public void how_to_use_subbing(){
        //return时thenReturn和doReturn功能一样
        Mockito.when(list.get(0)).thenReturn("first");
        Mockito.doReturn("second").when(list).get(1);

        Assert.assertEquals("first", list.get(0));
        Assert.assertEquals("second", list.get(1));

        //有返回值throw时用thenThrow
        Mockito.when(list.get(Mockito.anyInt())).thenThrow(new RuntimeException());
        try {
            list.get(0);
            fail();
        }catch (Exception e){
            Assert.assertThrows(RuntimeException.class,()->list.get(0));
        }
    }

    @Test
    public void how_to_subbing_return_void_method(){
        //对无返回值的方法Mock
        Mockito.doNothing().when(list).clear();
        list.clear();
        Mockito.verify(list,Mockito.times(1)).clear();
        //无返回值throw时用doThrow
        Mockito.doThrow(RuntimeException.class).when(list).clear();
        try {
            list.clear();
            fail();
        }catch (Exception e){
            Assert.assertThrows(RuntimeException.class,()->list.clear());
        }
    }
}

thenAnswer: Sets a generic Answer for the method

    @Test
    public void subbing_with_answer(){
        Mockito.when(list.get(Mockito.anyInt())).thenAnswer(new Answer() {
            public Integer answer(InvocationOnMock invocation) throws Throwable {
                return (Integer) invocation.getArguments()[0]*10;
            }
        });
        Assert.assertEquals(list.get(2),20);
        Assert.assertEquals(list.get(88),880);
    }

Mock可以通过thenCallRealMethod方法去执行真正的逻辑


    @Test
    public void subbing_with_real_call(){
        TestService service = Mockito.mock(TestService.class);
        Mockito.when(service.m1()).thenReturn("MockM1");
        Assert.assertEquals("MockM1", service.m1());

        Mockito.when(service.m2()).thenCallRealMethod();
        Assert.assertEquals("RealM2", service.m2());


    }
    
public class TestService {
    public String m1(){
        System.out.println("invoke TestService m1 method...");
        return "RealM1";
    }
    public String m2(){
        System.out.println("invoke TestService m2 method...");
        return "RealM2";
    }
}

三、Spy

当一个真正的对象被spy的时候,该对象可以被部分mock
spy和mock是相反功能。
spy:如果不对spy对象的methodA打桩,那么调用spy对象的methodA时,会调用真实方法。
mock:如果不对mock对象的methodA打桩,将doNothing,且返回默认值(null,0,false)。

@RunWith(MockitoJUnitRunner.class)
public class SpyTest {

    @Spy
    List<String> list = new ArrayList<>();

    @Test
    public void spyTest(){
        list.add("spy1");
        list.add("spy2");

        Assert.assertEquals("spy1",list.get(0));
        Assert.assertEquals("spy2",list.get(1));

        Mockito.when(list.isEmpty()).thenReturn(true);
        Mockito.doThrow(RuntimeException.class).when(list).clear();

        Assert.assertEquals("spy1",list.get(0)); //调用真实的方法
        Assert.assertEquals("spy2",list.get(1));//调用真实的方法
        Assert.assertTrue(list.isEmpty()); //spy对象的list.isEmpty()被mock了,就返回mock的值
        Assert.assertThrows(RuntimeException.class, ()->list.clear());//spy对象的list.isEmpty()被mock了,就返回mock的值
    }
}

四、 Matcher的参数

1) isA(),any(): 两者是一样的 用于配置指定类型的对象。以下是官方文档的解释
Matches any object of given type, excluding nulls.
This matcher will perform a type check with the given type, thus excluding values.
any(Class type) is an alias of isA(Class type)

import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;

public class IsAMethodTest {
    @Test
    public void isATest() {
        Foo foo = Mockito.mock(Foo.class);
        Mockito.when(foo.fun(Mockito.isA(Parent.class))).thenReturn(100); //需要配置类型为Parent的对象
        int cd1 = foo.fun(new Child1());
        int cd2 = foo.fun(new Child2());
        Assert.assertEquals(cd1, 100); //Child1类型为Parent 
        Assert.assertEquals(cd2, 100); //Child2类型为Parent 
    }

    class Foo {
        int fun(Parent p) {
            return p.work();
        }
    }

    interface Parent {
        int work();
    }

    class Child1 implements Parent {
        @Override
        public int work() {
            throw new RuntimeException();
        }
    }

    class Child2 implements Parent {

        @Override
        public int work() {
            throw new RuntimeException();
        }
    }
}

3) eq() :Object argument that is equal to the given value. 判断传入的参数是否跟指定的值相等
4) WildCard: anyInt(), anyDouble(), anyString(), anyList(), anyCollection()

@RunWith(MockitoJUnitRunner.class)
public class WildCardTest {

    @Mock
    WDService service;

    @Test
    public void testwd(){
        when(service.methodReturnint(anyInt(),anyString(),anyCollection(),isA(Serializable.class))).thenReturn(10);
        int res = service.methodReturnint(1,"qwe", Collections.emptyList(),"Mockito");
        Assert.assertEquals(10, res);
    }
    @Test
    public void testMethodReturnVoid(){
        doNothing().when(service).methodReturnVoid(anyInt(),anyString(),anyCollection(),isA(Serializable.class));
        service.methodReturnVoid(1,"qwe", Collections.emptyList(),"Mockito");
        //由于参数没有返回值,所以要判断方法的执行次数来验证
        verify(service,times(1)).methodReturnVoid(1, "qwe", Collections.emptyList(),"Mockito");
        //任意一个参数使用wildcard时, 其他也要使用wildcard。如果想指定特殊值,就要写在eq()内,否则拨错
        verify(service,times(1)).methodReturnVoid(anyInt(), eq("qwe"), anyCollection(), "Mockito");
    }
}

class WDService {

    public int methodReturnint(int i, String s, Collection c, Serializable b){
        throw new RuntimeException();
    }
    public void methodReturnVoid(int i, String s, Collection c, Serializable b){
        throw new RuntimeException();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值