0

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;
     }

Here is my feature :

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[];
            }
    }

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);
Ajay Kumar Jaiswal
  • 352
  • 1
  • 6
  • 24

1 Answers1

1

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.

  • 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.

  • 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.


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.

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.

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].

kriegaex
  • 63,017
  • 15
  • 111
  • 202
  • Thanks, @kriegaex. As you said, newbie that's true, I'm working on already written code but I'm blocked with other req, Once I'll back on the unit test I'll follow the guidelines you gave and certainly ask few questions if required. – Ajay Kumar Jaiswal Jun 30 '20 at 08:55
  • Hm, okay, so unit testing seems to be optional in your environment, not an integral part of coding such that coding is considered incomplete unless the code is covered by good tests. It seems to be something you can just interrupt for days (or be interrupted from outside) and do something "more important" instead. I think that testing as an engineering practice in general does not have a very bright future in whichever toxic environment so seem to be working. Good luck, pal! You have my sympathies. – kriegaex Jul 01 '20 at 06:33