如何测试从Spock中的外部调用实例化变量的函数 [英] How to test a function which instantiate a variable from external call in Spock

查看:92
本文介绍了如何测试从Spock中的外部调用实例化变量的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用Spock框架测试以下功能

Hi I want to test below function using Spock framework

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错误:无法在空对象上调用方法getHistoryDBConnectInfo().

It throwing error as java.lang.NullPointerException: Cannot invoke method getHistoryDBConnectInfo() on null object.

如何同时测试一个参数和三个参数的条件?

How can I test both the condition of getting condition with one parameter and three-parameter?

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

推荐答案

看看您的代码,您似乎是测试自动化的新手,而不仅仅是Spock新手.因此,让我首先提及一些基础知识:

Looking at your code, you seem to be a test automation newbie, not just a Spock newbie. So let me mention some basics first:

  • 您不应直接测试私有方法,而只能测试非私有方法.如果您不能轻易地以这种方式覆盖您的私有代码,则这表示可测试性差,并且通常表示应用程序设计不佳.如果您无法通过调用公共(或可能是程序包作用域)的方法来访问私有代码,则您的应用程序中可能存在死代码(未使用).因此,请删除无效代码和/或重构以提高可测试性.阅读一些测试教程或书籍应该会有所帮助.

  • You should not test private methods directly, only non-private ones. If you cannot easily cover your private code that way, it is a sign for bad testability and generally for bad application design. If you cannot reach private code by calling public (or maybe package-scoped) methods, you might have dead (unused) code in your application. So please remove the dead code and/or refactor for better testability. Reading some test tutorials or books should be helpful.

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

With regard to mock testing, you need to know that after you create a mock you also need to inject it into your class under test. Please search the web for dependency injection (DI). Briefly: You can inject mocks via constructor, setter, method parameter or DI frameworks such as CDI, EJB 3+, Spring, Guice.

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

If you cannot inject the mock, but your class under test creates its own dependencies internally, usually doing something like myLocalVariable = new MyDependency() or myField = new MyDependency(), that is bad news for anyone who wants to write automated tests for your code, including yourself. A mock dangling somewhere outside the class in which it is to be used (and thus completely unknown to it) will not help you much, unless you use "dirty" mocking tools like PowerMock or JMockit which can instrument the code under test in a way enabling them to intercept object creation. You should try to avoid that at all cost and refactor the application code instead.

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

In your concrete case, make sure to provide a method parameter, setter or constructor parameter for injecting the DBClient into your class. Then it is easy to call it from a test and inject a mock.

PS:您的例外是由于 mockRegistryClient null 的事实引起的,但是很遗憾,您没有提供

P.S.: Your exception is caused by the fact that mockRegistryClient is null, but unfortunately you do not provide an MCVE for your problem but only code snippets. The mockRegistryClient initialisation code is missing completely and I cannot debug something for you that I cannot see.

PPS:我想您不希望模拟返回 String [] ,因为它为一维字符串数组而不是数组返回 Class 类型实例本身.如果要返回零长度的字符串数组,则应使用 new String [0] ,但是在测试中,我看到您访问的数组索引为1、2、3.是在索引0中吗?您确实知道索引以0开头,而不是1,不是吗?)因此,您至少应该返回大小为4(索引0-3)或3(索引0-2)的数组,取决于您的要求,例如 new String [4] .

P.P.S.: I think you do not want your mock to return String[] because that returns a Class type instance for a one-dimensional string array, not the array itself. If you want to return a zero length string array, you should use new String[0], but in your test I see that you access array indices 1, 2, 3. (By the way, what is in index 0? You do know that indices start with 0, not 1, don't you?) So probably you should at least return an array of size 4 (indices 0-3) or 3 (indeces 0-2), depending on your requirement, i.e. something like new String[4].

这篇关于如何测试从Spock中的外部调用实例化变量的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆