Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mockito - mocking legacy class constructor

I am writing JUnit for a class that references a legacy class via constructor. The legacy class is in a third party jar, so I can't refactor it to make life easier....

This is the class being tested...

public MyClass {

    public String methodToTest(String param) {
        LegacyClass legacy = new LegacyClass(param);
        *..... etc ........*
    }
}

This is what I am trying to do in the mockito JUnit.

public MyClassTest {

    @Test
    public void testMethodToTest() throws Exception {
        LegacyClass legacyMock = mock(LegacyClass.class);
        when(*the LegacyClass constructor with param is called*).thenReturn(legacyMock);
        *.... etc.....*
    }
}

Any ideas on how I can do this ?????

like image 445
Dave Avatar asked Jun 09 '11 05:06

Dave


People also ask

Can I mock a constructor using Mockito?

Starting with Mockito version 3.5. 0, we can now mock Java constructors with Mockito. This allows us to return a mock from every object construction for testing purposes.

Which are used to create a mock implementation?

Mocks are a full replacement for dependency and can be programmed to return the specified output whenever a method on the mock is called. Mockito provides a default implementation for all the methods of a mock.


2 Answers

Make a builder for the LegacyClass:

public class LegacyClassBuilder {

    public LegacyClass build(String param) {
        return new LegacyClass(param);
    }

}

That way your class can be tested so it creates the LegacyClass with correct parameter.

public MyClass {

    private LegacyClassBuilder builder;

    public setBuilder(LegacyClassBuilder builder) {
        this.builder = builder;
    }

    public String methodToTest(String param) {
        LegacyClass legacy = this.builder.build(param);
        ... etc
    }
}

The test will look something like this:

// ARRANGE
LegacyClassBuilder mockBuilder = mock(LegacyClassBuilder.class);
LegacyClass mockLegacy = mock(LegacyClass.class); 
when(mockBuilder.build(anyString()).thenReturn(mockLegacy);

MyClass sut = new MyClass();
sut.setBuilder(mockBuilder);
String expectedParam = "LOLCAT";


// ACT
sut.methodToTest(expectedParam);

// ASSERT
verify(mockBuilder).build(expectedParam);

If LegacyClass happens to be final then you need to create non-final wrapper for LegacyClass that MyClass will use.

like image 79
Spoike Avatar answered Oct 27 '22 09:10

Spoike


You can use PowerMockito framework:

import static org.powermock.api.mockito.PowerMockito.*;

whenNew(LegacyClass.class)
  .withParameterTypes(String.class)
  .withArguments(Matchers.any(String.class))
  .thenReturn(new MockedLegacyClass(param));

Then write your MockedLegacyClass implementation according to your test needs.

like image 33
user1645629 Avatar answered Oct 27 '22 09:10

user1645629