简体   繁体   English

为什么使用Mockito进行JUnit测试而无需定义“何时”方法?

[英]Why JUnit test with Mockito work without defining “when” method?

I am trying to test a scenario with empty database/ nothing returned from database. 我正在尝试测试数据库为空/数据库未返回任何内容的情况。

I wrote a junit4 test class with mockito. 我用Mockito编写了一个junit4测试类。 There is a service class and dao class created by mockito. 由嘲讽创建一个服务类和dao类。 At first, I defined the "when" method and it worked. 首先,我定义了“ when”方法,并且它起作用了。 Later, I tried to pull the "when" method calls and see what would happen, it worked anyway. 后来,我尝试拉出“ when”方法调用,看看会发生什么,无论如何它都起作用。 Why? 为什么?

The class myService would call all four methods of myDao when myService.getDistinctObjectList() is called. 调用myService.getDistinctObjectList()时,类myService将调用myDao的所有四个方法。 So I thought I have to mock all four methods and return dummy result. 所以我认为我必须模拟所有四种方法并返回虚拟结果。 What would happen if myDao.someMethod() is called when it is not configured? 如果未配置myDao.someMethod()时会发生什么情况? MyDao is supposed to work with a database but I didn't give anything to it. MyDao应该与数据库一起使用,但是我什么也没做。

I attached the sample code of MyDao and MyService for reference. 我附上了MyDao和MyService的示例代码,以供参考。 ( I simplified them, MyDao has four methods which retrieve four kinds of object) (我简化了它们,MyDao有四种检索四种对象的方法)

public class MyDaoImpl implements MyDao {
    @SuppressWarnings("unused")
    private DataSource dataSource;
    private JdbcTemplate jdbcTemplate;
    private String schema;

    @ConstructorProperties({ "dataSource", "schema" })
    private MyDaoImpl(DataSource dataSource, String schema) {
        this.dataSource = dataSource;
        this.schema = schema;
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    @Override
    public List<SomeObjectTypeA> listSomeObjectTypeA() {
        return this.jdbcTemplate.query("select * from " + schema + ".SOME_TABLE", new RowMapper<SomeObjectTypeA>() {
            @Override
            public SoftBillAccount mapRow(ResultSet rs, int rowNum) throws SQLException {
                String memberA = rs.getString("MEMBER_A");
                String memberB = rs.getString("MEMBER_B");
            }
        });

    }
    public List<SomeObjectTypeA> listSomeObjectTypeB() {
        //omitted
    }
    public List<SomeObjectTypeA> listSomeObjectTypeC() {
        //omitted
    }
    public List<SomeObjectTypeA> listSomeObjectTypeD() {
        //omitted
    }
}

public class MyServiceImpl implements MyService {

    private MyDao myDao;

    public MyServiceImpl(){}

    @ConstructorProperties({ "myDao" })
    public MyServiceImpl(MyDao myDao) {
        this.myDao = myDao;
    }

    @Override
    public List<String> getSomeObjectTypeA_MemberA_Only() {
        List<SomeObjectTypeA> list = myDao.listSomeObjectTypeA();
        List<String> memberAList = new ArrayList<String>();
        for (SomeObjectTypeA objectA : list) {
            memberAList.add(objectA.getMemberA());
        }
        return memberAList;
    }
}



public class MyServiceImpl implements MyService {

    private MyDao myDao;

    public MyServiceImpl(){}

    @ConstructorProperties({ "myDao" })
    public MyServiceImpl(MyDao myDao) {
        this.myDao = myDao;
    }

    @Override
    public List<String> getSomeObjectTypeA_MemberA_Only() {
        List<SomeObjectTypeA> list = mydao.listSomeObjectTypeA();
        List<String> memberAList = new ArrayList<String>();
        for (SomeObjectTypeA objectA : list) {
            memberAList.add(objectA.getMemberA());
        }
        return memberAList;
    }
}

This is the Test class: 这是Test类:

public class Test1{

    @InjectMocks
    private MyServiceImpl myService;

    @Mock
    private MyDao myDao;

    @Before
    public void init() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testEmptyDatabase() {

        //ArrayList<SomeObjectTypeA> list = new ArrayList<SomeObjectTypeA>();
        //list.add( new SomeObjectTypeA("A","A", "A", "A") );
        //when(myDao.listSomeObjectTypeA()).thenReturn( Collections.<SomeObjectTypeA>emptyList() );
        //when(myDao.listSomeObjectTypeB()).thenReturn( Collections.<SomeObjectTypeB>emptyList() );
        //when(myDao.listSomeObjectTypeC()).thenReturn( Collections.<SomeObjectTypeC>emptyList() );
        //when(myDao.listSomeObjectTypeD()).thenReturn( Collections.<SomeObjectTypeD>emptyList() );

        List<String> distinctList = myService.getDistinctObjectList(); // myService.getDistinctObjectList() end up calling all four methods of myDao

        //Write the List to a file, with a trailer with record count
        OutputWriter outputWriter = new OutputWriterImpl(outputFileDir, outputFilePrefix,outputFileSuffix);
        try{
            outputWriter.writeOutput(distinctList);
        }catch(IOException e){
            e.printStackTrace();
        }

        //Create a control file for comparison
        try{
            BufferedWriter bfr = new BufferedWriter(new FileWriter(compareFileDir+compareFilePrefix+compareFileSuffix));
            bfr.write("Trailer|");
            bfr.write(String.format("%07d", 0));
            bfr.newLine();
            bfr.close();
        }catch(IOException e){
            e.printStackTrace();
        }
        File file1 = new File(outputFileDir + outputFilePrefix + date + outputFileSuffix);
        File file2 = new File(compareFileDir+ compareFilePrefix+compareFileSuffix);

        System.out.println(file1.length()); // show 17
        System.out.println(file2.length()); // show 17

        assertEquals(file1.length(), file2.length());
    }

Unless you explicitly change the mock's default behavior, it will return "nice values" . 除非您明确更改模拟的默认行为,否则它将返回“ nice values” For collection, the default return value is an empty collection, so you don't need to explicitly use a when call to return such empty collections as your commented out code does. 对于集合,默认的返回值是一个空集合,因此您不需要像注释掉的代码那样显式地使用when调用来返回此类空集合。

What would happen if myDao.someMethod() is called when it is not configure? 如果未配置myDao.someMethod(),将如何处理?

With plain mockito (so without spy usage that call the read method), it will not throw any exception or error, it will simply implement the method as an empty body. 使用普通的模仿(因此无需调用read方法的间谍使用),它不会引发任何异常或错误,它只会将方法实现为空主体。 Then if the method is declared as void , no additional behavior is required and if the method is declared with a return type, it returns the default value of the declared type result that is null reference for objects but for collections where Mockito returns an empty instance of them and at last default values for primitives. 然后,如果该方法声明为void ,则不需要任何其他行为,并且如果该方法声明为带有返回类型,则它返回已声明类型结果的默认值,该默认值是对象的null引用,但对于Mockito返回空实例的集合而言它们,最后是基元的默认值。

But note that generally this feature of Mockito doesn't cause any side effect in your test logic as generally you want to assert the content of the Lists and not only their non nullity. 但请注意,通常,Mockito的此功能不会在测试逻辑中引起任何副作用,因为通常您要声明列表的内容,而不仅是声明它们的非无效性。
But in your case you mock empty Lists : 但是在您的情况下,您模拟了空的List:

when(myDao.listSomeObjectTypeB()).thenReturn( Collections.<SomeObjectTypeB>emptyList() );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM