5

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

Mockito.doNothing().when(dataSource).update(
Mockito.any(DataSource.class),  Mockito.any(ArrayList.class), Mockito.anyInt());

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

您的建议将不胜感激。

4

1 回答 1

2

是的,代理类是解决 3rd 方类这些类型问题的一种方法。然后,您可以简单地模拟您的代理类而不是 3rd 方类,而不会产生任何影响。这种方法的缺点是您最终会使用这些额外的包装类来支持您的测试。

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

public class UpdateManagerFactory {

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

如果您使用 Spring 或类似的方式进行依赖注入,则可以在应用程序上下文中将此 Factory 用作单例 bean,因此需要将其设为static. 如果你确实想让这个 Factory 静态,你可以使用powermockito来模拟它。

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


按照您的评论进行编辑

不要为您的工厂类使用 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"

}
于 2013-02-07T12:56:58.033 回答