簡體   English   中英

為什么使用Mockito進行JUnit測試而無需定義“何時”方法?

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

我正在嘗試測試數據庫為空/數據庫未返回任何內容的情況。

我用Mockito編寫了一個junit4測試類。 由嘲諷創建一個服務類和dao類。 首先,我定義了“ when”方法,並且它起作用了。 后來,我嘗試拉出“ when”方法調用,看看會發生什么,無論如何它都起作用。 為什么?

調用myService.getDistinctObjectList()時,類myService將調用myDao的所有四個方法。 所以我認為我必須模擬所有四種方法並返回虛擬結果。 如果未配置myDao.someMethod()時會發生什么情況? MyDao應該與數據庫一起使用,但是我什么也沒做。

我附上了MyDao和MyService的示例代碼,以供參考。 (我簡化了它們,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;
    }
}

這是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());
    }

除非您明確更改模擬的默認行為,否則它將返回“ nice values” 對於集合,默認的返回值是一個空集合,因此您不需要像注釋掉的代碼那樣顯式地使用when調用來返回此類空集合。

如果未配置myDao.someMethod(),將如何處理?

使用普通的模仿(因此無需調用read方法的間諜使用),它不會引發任何異常或錯誤,它只會將方法實現為空主體。 然后,如果該方法聲明為void ,則不需要任何其他行為,並且如果該方法聲明為帶有返回類型,則它返回已聲明類型結果的默認值,該默認值是對象的null引用,但對於Mockito返回空實例的集合而言它們,最后是基元的默認值。

但請注意,通常,Mockito的此功能不會在測試邏輯中引起任何副作用,因為通常您要聲明列表的內容,而不僅是聲明它們的非無效性。
但是在您的情況下,您模擬了空的List:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM