Groovy 如何在Spock中测试从外部调用实例化变量的函数

Groovy 如何在Spock中测试从外部调用实例化变量的函数,groovy,spock,Groovy,Spock,嗨,我想用Spock框架测试下面的函数 private Connection getDBConnection() throws SQLException { DBClient client = DBService.getClient() String[] connInfo = client.getHistoryDBConnectInfo() String url = connInfo[1]; S

嗨,我想用Spock框架测试下面的函数

private Connection getDBConnection() throws SQLException
     {
         DBClient client = DBService.getClient()
         
         String[] connInfo = client.getHistoryDBConnectInfo()
         String url = connInfo[1];
         String user = connInfo[2];
         String pwd = connInfo[3];

         Connection conn;
         if(!StringUtils.containsIgnoreCase(url,"Authentication=ActiveDirectoryMsi"))
             conn = DriverManager.getConnection(url, user, pwd);
         else
             conn= DriverManager.getConnection(url);
         return conn;
     }
以下是我的特色:

def setup() {
        service = Mock(DBService.class)
        mockClient = Mock(DBClient.class)
    }

def "get the connection for AzureActiveDirectoryMSI"() {

        when:
            service.getDBConnection()
        then:
            1 * mockRegistryClient.getHistoryDBConnectInfo()>>{
                return String[];
            }
    }
它抛出错误为java.lang.NullPointerException:无法在null对象上调用方法GetHistoryDBConnectionInfo()

如何测试获取一个参数和三个参数条件的条件

1.    DriverManager.getConnection(url, user, pwd);
2.    DriverManager.getConnection(url);

看看你的代码,你似乎是一个测试自动化新手,而不仅仅是一个斯波克新手。因此,让我先介绍一些基本知识:

  • 您不应该直接测试私有方法,而应该只测试非私有方法。如果您不能很容易地用这种方式覆盖您的私有代码,那么这是坏的可测试性的标志,通常是坏的应用程序设计的标志。如果您无法通过调用公共(或者包作用域)方法来访问私有代码,则应用程序中可能存在死(未使用)代码。因此,为了更好的可测试性,请删除死代码和/或重构。阅读一些测试教程或书籍应该会有所帮助

  • 关于模拟测试,您需要知道,在创建模拟之后,还需要将其注入到被测试的类中。请在web上搜索依赖项注入(DI)。简单地说:您可以通过构造函数、setter、方法参数或DI框架(如CDI、EJB3+、Spring、Guice)注入模拟

  • 如果您无法注入模拟,但您的被测类在内部创建了自己的依赖项,通常会执行类似于
    myLocalVariable=new MyDependency()
    myField=new MyDependency()
    的操作,这对于任何想要为您的代码编写自动测试的人来说都是个坏消息,包括您自己。挂在要使用它的类之外的某个地方的模拟(因此它完全不知道)不会对您有多大帮助,除非您使用“脏”的模拟工具,如PowerMock或JMockit,它可以以某种方式对测试中的代码进行检测,使它们能够拦截对象创建。您应该不惜一切代价避免这种情况,而是重构应用程序代码


在具体的情况下,确保提供一个方法参数、setter或构造函数参数,用于将
DBClient
注入类中。然后很容易从测试调用它并注入模拟

注意:
mockRegistryClient
null
,这一事实导致了您的异常,但不幸的是,您没有为您的问题提供解决方案,只提供了代码片段。
mockRegistryClient
初始化代码完全丢失,我无法为您调试一些我看不到的东西


p.p.S.:我认为您不希望您的模拟返回
String[]
,因为它返回一维字符串数组的
Class
类型实例,而不是数组本身。如果要返回零长度字符串数组,应该使用
新字符串[0]
,但在测试中,我看到您访问了数组索引1、2、3。(顺便问一下,索引0中是什么?你知道索引是以0开始的,不是以1开始的,不是吗?)因此,根据你的要求,你可能至少应该返回一个大小为4(索引0-3)或3(索引0-2)的数组,例如
新字符串[4]

谢谢,@kriegaex。正如你所说的,新手没错,我正在编写已经编写好的代码,但是我被其他请求阻止了,一旦我回到单元测试,我将遵循你给出的指导原则,如果需要,当然会问一些问题。嗯,好吧,所以单元测试在你的环境中似乎是可选的,不是编码的一个组成部分,因此除非代码被良好的测试覆盖,否则编码被认为是不完整的。这似乎是你可以中断几天(或被外界打断)然后做一些“更重要”的事情。我认为,测试作为一种工程实践,在任何有毒环境中都不会有非常光明的前景,因此似乎正在发挥作用。祝你好运,朋友!我同情你。