Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking a Class with constructor parameter

I need to mack a class for testing. The problem is i am using third party library where the class(UpdateManager) constructor takes 5 arguments i.e one java.sql.Connection and others are string. Inside that constructor it creates one class instance(DataSource) by passing constructor argument as connection. In that data source instance it calls one of its method which invokes stored procedure. My problem is i created partial mocking of UpdateManager by passing those 5 parameter with mocked connection but inside constructor when in invokes the method on DataSource it throws null pointer exception. Before i stubbed the DataSource by given below

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

Still its throwing NullPointException as everytime the constructor creates new instance of DataSource. How do i mock it in this scenario without db connection only throwing my stubbed exception or doNothing.I used MOCKITO.Is there any better solution using proxy pattern on this.

Your Suggestion will be appreciated .

like image 339
Anil Avatar asked Nov 03 '22 05:11

Anil


1 Answers

Yes, a proxy class is one way to resolve these types of issues with 3rd party classes. You can then simply mock your proxy class instead of the 3rd party classes without implications. The downside to this approach is you end up with these additional wrapper classes just to support your testing.

In this specific case it may be beneficial for you to add a Factory class to act as the proxy, seeing as you're interested in the creation of these UpdateManager objects

public class UpdateManagerFactory {

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

If you're using Spring or similar for your dependency injection you can get away with this Factory being a singleton bean in your application context, so need to make it static. If you do want to make this Factory static you can use powermockito to mock it.

Tip: Don't be afraid to add code in order to make your application easier to test


Edit following your comments

Don't use a spy() for your Factory class, mock it instead

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"

}
like image 167
Brad Avatar answered Nov 08 '22 08:11

Brad