Java 使用构造函数参数模拟类

Java 使用构造函数参数模拟类,java,mocking,mockito,Java,Mocking,Mockito,我需要考一门课。问题是我使用的是第三方库,其中类(UpdateManager)构造函数接受5个参数,即一个java.sql.Connection,其他参数是string。在该构造函数中,它通过将构造函数参数作为连接传递来创建一个类实例(数据源)。在该数据源实例中,它调用其调用存储过程的方法之一。我的问题是,我创建了UpdateManager的部分模拟,通过使用模拟连接传递这5个参数,但在构造函数内部,当in调用DataSource上的方法时,它抛出空指针异常。在我用下面给出的方法对数据源进行st

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

Mockito.doNothing().when(dataSource).update(
Mockito.any(DataSource.class),  Mockito.any(ArrayList.class), Mockito.anyInt());
每次构造函数创建数据源的新实例时,仍然会抛出NullPointException。在这种情况下,如果db连接没有抛出stubbed异常或其他异常,我该如何模拟它。我使用了MOCKITO。有没有更好的解决方案使用代理模式呢


非常感谢您的建议。

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

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

public class UpdateManagerFactory {

    public UpdateManager createInstance(... args...) {
        return new UpdateManager(... args...);
    }
}
如果您使用Spring或类似工具进行依赖项注入,那么这个工厂在您的应用程序上下文中是一个单例bean,因此需要将它设置为静态的。如果您确实想使这个工厂成为静态的,您可以使用它来模拟它

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


根据您的评论编辑

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

}

我使用的工厂通过使用Mockito.spy()创建UpdateManager部分模拟。但此UpdateManager构造函数使用UpdateManager的连接参数创建数据源实例,该参数进一步用于存储过程。由于我无法控制数据源,因此当它调用其方法时会引发异常。我感谢您的重播,但希望不会通过模拟代理类或Spy()来解决此问题.您不希望在单元测试中使用真正的
数据源
对象(请参见上面的编辑)。事实上,如果可以的话,你也不想加载你的第三方类。我假设你不是在试图编写一个测试数据库的集成测试。我的意思就是说上面的一点。一些疑问仍然需要检查一些东西。如果有,请告诉你。谢谢Brad。