简体   繁体   中英

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. There is a service class and dao class created by mockito. At first, I defined the "when" method and it worked. Later, I tried to pull the "when" method calls and see what would happen, it worked anyway. Why?

The class myService would call all four methods of myDao when myService.getDistinctObjectList() is called. 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 is supposed to work with a database but I didn't give anything to it.

I attached the sample code of MyDao and MyService for reference. ( I simplified them, MyDao has four methods which retrieve four kinds of object)

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:

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" . 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.

What would happen if myDao.someMethod() is called when it is not configure?

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. 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.

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.
But in your case you mock empty Lists :

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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