jmockito模拟方法中参数如何指定

本文通过实例探讨了在使用Mockito进行单元测试时,如何正确地mock类的方法。特别是针对基本类型和复杂类型的参数,详细介绍了mock成功的条件,并总结了mock参数与实际参数之间的关系。

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

在做单元测试的时候,经常会遇到mock类的方法的情景。在写单测过程中,遇到一些问题,比较困惑,便做了一些测试,并得出一个结论:
在mock类的方法时,当符合 (mock参数).equals(实际调用过程中的参数)时,才可以mock成功;当参数为基本类型时,可以使用angLong等。

下面是测试的欢乐时间啦:
首先看测试基础类:

public class Person {
    private String name;
    private Integer age;
    private Person friend;
}

public class PersonService {

    public void showFriendInfo(Person person){
        System.out.println("show friend info ...");
        showInfo1(new Person("shoren", 22));
        showInfo2(person.getFriend());
    }

    public void showInfo1(Person person){
        System.out.println("show info1 ...");
    }

    public void showInfo2(Person person){
        System.out.println("show info2 ...");
    }

    public void showPersonInfo(Person person){
        System.out.println("show person info ...");
        showName("shoren");
        showName2(person.getName());

    }

    public void showName(String name){
        System.out.println("show name1 : " + name);
    }

    public void showName2(String name){
        System.out.println("show name2 : " + name);
    }

}    

先看参数为基本类型时:

1. 参数为基本类型时,使用any都可以成功mock。
    @Test
    public void testShowPersonInfoUsingAny(){
        final Person person = new Person("manyao", 23);

        new NonStrictExpectations(personService){{
            Deencapsulation.invoke(personService, "showName", anyString);
            Deencapsulation.invoke(personService, "showName2", anyString);
        }};
        personService.showPersonInfo(person);
    }

结果为

show person info ...
2. 参数为基本类型,mock时传入真实的值,且与之前值相等,可以mock成功。
    @Test
    public void testShowPersonInfoUsingData(){
        final Person person = new Person("manyao", 23);

        new NonStrictExpectations(personService){{
            Deencapsulation.invoke(personService, "showName", new String("shoren"));
            Deencapsulation.invoke(personService, "showName2", new String("manyao"));
        }};
        personService.showPersonInfo(person);
    }

结果为:

show person info ...
3. 参数为基本类型,mock时传入真实的值,若实际调用值与之不相等,则mock失败。
    @Test
    public void testShowPersonInfoUsingData2(){
        final Person person = new Person("manyao", 23);

        new NonStrictExpectations(personService){{
            Deencapsulation.invoke(personService, "showName", new String("tata"));
            Deencapsulation.invoke(personService, "showName2", person.getName());
        }};
        personService.showPersonInfo(person);
    }

结果为

     show person info ...
     show name1 : shoren

得出结论:如果参数为基本类型,则mock参数为anyXXX 或者 与实际调用的参数值相等时,可以mkco成功。

再来看参数为复杂类型:

4. 参数为复杂参数时,使用any做类型转换,mock失败。
    @Test
    public void testShowFriendUseAny(){
        final Person person = new Person("manyao", 23);
        person.setFriend(new Person("friend", 24));

        new NonStrictExpectations(personService){{
            Deencapsulation.invoke(personService, "showInfo1", (Person)any);
            Deencapsulation.invoke(personService, "showInfo2", (Person)any);
        }};
        personService.showFriendInfo(person);
    }

结果为

     java.lang.IllegalArgumentException: Invalid null value passed as argument 0
     at jmockito.PersonServiceTest$4.<init>(PersonServiceTest.java:92)
     at jmockito.PersonServiceTest.testShowFriendUseAny(PersonServiceTest.java:91)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
     at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
     at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
     at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
5. 参数为复杂参数,mock参数为具体值时,mock参数 equals 实际调用值时,mock成功。
    @Test
    public void testShowFriendUseData(){
        final Person person = new Person("manyao", 23);
        person.setFriend(new Person("friend", 24));

        new NonStrictExpectations(personService){{
            Deencapsulation.invoke(personService, "showInfo1", new Person("shoren", 22));
            Deencapsulation.invoke(personService, "showInfo2", person.getFriend());
        }};
        personService.showFriendInfo(person);
    }

结果为

     show friend info ...
     show info1 ...

到这里,似乎可以得出这样一个结论,mock内部调用方法时,其mock参数与外部参数的关系,应该与实际执行时,参数的关系一致。即实际调用中,showInfo2的参数是person.getFriend(),
所以,在mock方法showInfo2时,其参数也应该是person.getFriend()。
如果是这样的话,mock方法showInfo1时,又该如何呢?在Person中添加equals方法测试一下。

6. 参数为复杂参数时,(mock参数).equals(实际参数)时,mock成功。
    @Test
    public void testShowFriendUseData1(){
        final Person person = new Person("manyao", 23);
        person.setFriend(new Person("friend", 24));

        new NonStrictExpectations(personService){{
            Deencapsulation.invoke(personService, "showInfo1", new Person("shoren", 22));
            Deencapsulation.invoke(personService, "showInfo2", new Person("friend", 24));
        }};
        personService.showFriendInfo(person);
    }

结果为

show friend info ...
7. 参数为复杂参数时,修改equals方法,总是return true时。不论mock参数如何,mock成功.
     @Test
    public void testShowFriendUseData2(){
        final Person person = new Person("manyao", 23);
        person.setFriend(new Person("friend", 24));

        new NonStrictExpectations(personService){{
            Deencapsulation.invoke(personService, "showInfo1", new Person());
            Deencapsulation.invoke(personService, "showInfo2", new Person());
        }};
        personService.showFriendInfo(person);
    }

结果为

 show friend info ...

综上,我们得出结论:
在mock类的方法时,当符合 (mock参数).equals(实际调用过程中的参数)时,才可以mock成功;当参数为基本类型时,可以使用angLong等。

当然,像这一类的问题,如果要了解清楚,最好还是去阅读源代码。暂时没有时间做这件事。

转载于:https://www.cnblogs.com/shoren/p/jmockito-test.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值