使用构造函数参数模拟类

时间:2013-02-07 12:37:55

标签: java mocking mockito

我需要测试一个类进行测试。问题是我使用第三方库,其中类(UpdateManager)构造函数采用5个参数,即一个java.sql.Connection,其他是字符串。在该构造函数中,它通过将构造函数参数作为连接传递来创建一个类实例(DataSource)。在该数据源实例中,它调用其调用存储过程的方法之一。我的问题是我创建了部分模拟UpdateManager,通过使用模拟连接传递这5个参数但在构造函数内部调用DataSource上的方法时抛出空指针异常。在我通过下面的

来描述DataSource之前
Mockito.doNothing().when(dataSource).update(
Mockito.any(DataSource.class),  Mockito.any(ArrayList.class), Mockito.anyInt());

每次构造函数创建DataSource的新实例时,仍会抛出NullPointException。我如何在没有数据库连接的情况下模拟它只抛出我的存根异常或doNothing.I使用MOCKITO.Is有更好的解决方案使用代理模式。

您的建议将不胜感激。

1 个答案:

答案 0 :(得分:2)

是的,代理类是解决第三方类的这些类型问题的一种方法。然后,您可以简单地模拟代理类而不是第3方类而不会产生影响。这种方法的缺点是你最终得到这些额外的包装类只是为了支持你的测试。

在这种特定情况下,添加Factory类作为代理可能是有益的,因为您对创建这些UpdateManager对象感兴趣

public class UpdateManagerFactory {

    public UpdateManager createInstance(... args...) {
        return new UpdateManager(... args...);
    }
}

如果您正在使用Spring或类似的依赖注入,那么您可以在应用程序上下文中使用此Factory作为单例bean,因此需要将其设为static。如果您确实希望将此Factory静态化,可以使用powermockito进行模拟。

提示:不要害怕添加代码以使您的应用程序更易于测试


修改后面的评论

不要在您的Factory类中使用spy(),而是将其模拟为

public void myTest() {

    Foo classUnderTest = new Foo();

    UpdateManagerFactory umf = mock(UpdateManagerFactory.class);

    UpdateManager um = mock(UpdateManager.class);

    when(umf.createInstance()).thenReturn(um);

    // perform test that will call umf.createInstance() at some point
    classUnderTest.doSomething();

    // verify + assert on "umf" and "um"

}