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


    在做单元测试的时候,经常会遇到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等。

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

  • 相关阅读:
    Test
    占位2
    开坑纪念
    function 类型(函数定义)----读书总结
    css位元素 after
    算法-哈希表
    CF547D
    CF538H
    CF516D
    CF505E
  • 原文地址:https://www.cnblogs.com/shoren/p/jmockito-test.html
Copyright © 2020-2023  润新知