使用模拟对象进行junit测试:存根内部函数调用

时间:2012-12-14 18:42:11

标签: java unit-testing junit mockito

所以我尝试测试ping()方法并确保它调用connect()disconnect()。我嘲笑了对象foo和对象Connection。然后我做stub(mockFoo.connect()).toReturn(mockConn)希望然后ping()应该返回true给我断言。然而,不知何故,这种存根不会经历。我怀疑可能在内部调用connect时,mockFoo实际上没有调用connect(),因此没有返回模拟连接,但我不确定。

public class foo{
    public boolean ping(){
        bool ping = false; 
        Connection conn = null;
        try{
           conn = connect();
           ping = true;
        }catch(Exception e){
        }finally{
           disconnect(conn);
        }
        return ping;
    }

    public Connection connect(){
        //some implementation
        return connect
    }

1 个答案:

答案 0 :(得分:5)

通常你不会模拟被测单元本身。 Mockito将对所有方法使用默认存根行为。因此,对ping()的调用只会返回默认的false,而且不会调用foo的其他方法。

你可以通过在foo上制作间谍来进行局部模拟,然后按照你的方式存根连接方法。虽然我不推荐这个。 理想情况下,您将注入协作者(在本例中为Connection)的依赖关系。建立连接和使用连接是不同的职责,并且真正属于不同的类。

更像这样:

public class Foo {

    private final ConnectionProvider connectionProvider;

    private Foo(ConnectionProvider connectionProvider) {
        this.connectionProvider = connectionProvider;
    }

    public boolean ping(){
            boolean ping = false;
            Connection connection = null;
            try{
                connection = connectionProvider.getConnection();
                ping = true;
            }catch(Exception e){
                // TODO handle this exception
            }finally{
                try {
                    connection.close();
                } catch (SQLException e) {
                    // TODO handle this exception
                }
            }
            return ping;
        }

}

public interface ConnectionProvider {

    Connection getConnection();
}

@org.junit.Test
public void testConnection() throws Exception {
    ConnectionProvider mockProvider = mock(ConnectionProvider.class);
    Connection mockConnection = mock(Connection.class);
    when(mockProvider.getConnection()).thenReturn(mockConnection);

    Foo foo = new Foo(mockProvider);

    assertTrue(foo.ping());

    verify(mockConnection).close();
}