Unit testing with mockito for constructors

JavaUnit TestingMockito

Java Problem Overview


I have one class.

Class First {

    private Second second;

    public First(int num, String str) {
        second = new Second(str);
        this.num = num;
    }

    ... // some other methods
}

I want to write unit tests for public methods of class First. I want to avoid execution of constructor of class Second.

I did this:

Second second = Mockito.mock(Second.class);
Mockito.when(new Second(any(String.class))).thenReturn(null);
First first = new First(null, null);

It is still calling constructor of class Second. How can i avoid it?

Java Solutions


Solution 1 - Java

You can use PowerMockito

See the example:

Second second = Mockito.mock(Second.class);
whenNew(Second.class).withNoArguments().thenReturn(second);

But re-factoring is better decision.

Solution 2 - Java

Once again the problem with unit-testing comes from manually creating objects using new operator. Consider passing already created Second instead:

class First {

  private Second second;

  public First(int num, Second second) {
    this.second = second;
    this.num = num;
  }

  // some other methods...
}

I know this might mean major rewrite of your API, but there is no other way. Also this class doesn't have any sense:

Mockito.when(new Second(any(String.class).thenReturn(null)));

First of all Mockito can only mock methods, not constructors. Secondly, even if you could mock constructor, you are mocking constructor of just created object and never really doing anything with that object.

Solution 3 - Java

Here is the code to mock this functionality using PowerMockito API.

Second mockedSecond = PowerMockito.mock(Second.class);
PowerMockito.whenNew(Second.class).withNoArguments().thenReturn(mockedSecond);

You need to use Powermockito runner and need to add required test classes (comma separated ) which are required to be mocked by powermock API .

@RunWith(PowerMockRunner.class)
@PrepareForTest({First.class,Second.class})
class TestClassName{
    // your testing code
}
        

Solution 4 - Java

I have used "Pattern 2 - the "factory helper pattern"

> ### Pattern 2 - the factory helper pattern > > One case where this pattern won't work is if MyClass is final. Most of the Mockito framework doesn't play particularly well with final classes; and this includes the use of spy(). Another case is where MyClass uses getClass() somewhere, and requires the resulting value to be MyClass. This won't work, because the class of a spy is actually a Mockito-generated subclass of the original class. > > In either of these cases, you'll need the slightly more robust factory helper pattern, as follows. > > public class MyClass{ > static class FactoryHelper{ > Foo makeFoo( A a, B b, C c ){ > return new Foo( a, b, c ); > } > } >
> //... >
> private FactoryHelper helper; > public MyClass( X x, Y y ){ > this( x, y, new FactoryHelper()); > } >
> MyClass( X x, Y, y, FactoryHelper helper ){ >
> //... >
> this.helper = helper; > } >
> //... >
> Foo foo = helper.makeFoo( a, b, c ); > } > > So, you have a special constructor, just for testing, that has an additional argument. This is used from your test class, when creating the object that you're going to test. In your test class, you mock the FactoryHelper class, as well as the object that you want to create. >
> @Mock private MyClass.FactoryHelper mockFactoryHelper; > @Mock private Foo mockFoo; > private MyClass toTest; > > and you can use it like this >
> toTest = new MyClass( x, y, mockFactoryHelper ); > when( mockFactoryHelper.makeFoo( > any( A.class ), any( B.class ), any( C.class ))) > .thenReturn( mockFoo );

Source: http://web.archive.org/web/20160322155004/http://code.google.com/p/mockito/wiki/MockingObjectCreation

Solution 5 - Java

Mockito can now mock constructors (since version 3.5.0) https://javadoc.io/static/org.mockito/mockito-core/3.5.13/org/mockito/Mockito.html#mocked_construction

try (MockedConstruction mocked = mockConstruction(Foo.class)) {
   Foo foo = new Foo();
   when(foo.method()).thenReturn("bar");
   assertEquals("bar", foo.method());
   verify(foo).method();
 }

Solution 6 - Java

I believe, it is not possible to mock constructors using mockito. Instead, I suggest following approach

Class First {
        
   private Second second;
        
   public First(int num, String str) {
     if(second== null)
     {
       //when junit runs, you get the mocked object(not null), hence don't 
       //initialize            
       second = new Second(str);
     }
     this.num = num;
   }
    
   ... // some other methods
}

And, for test:

class TestFirst{
    @InjectMock
    First first;//inject mock the real testable class
    @Mock
    Second second

    testMethod(){

        //now you can play around with any method of the Second class using its 
        //mocked object(second),like:
        when(second.getSomething(String.class)).thenReturn(null);
    }
}

Solution 7 - Java

Include this line on top of your test class

@PrepareForTest({ First.class })

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTarun KumarView Question on Stackoverflow
Solution 1 - JavatermaView Answer on Stackoverflow
Solution 2 - JavaTomasz NurkiewiczView Answer on Stackoverflow
Solution 3 - JavaRocky MenaView Answer on Stackoverflow
Solution 4 - JavaVelibor DragutinovićView Answer on Stackoverflow
Solution 5 - JavadistanteView Answer on Stackoverflow
Solution 6 - JavaRishabh SachdevaView Answer on Stackoverflow
Solution 7 - JavaRamesh VView Answer on Stackoverflow