Unit testing with mockito for constructors

后端 未结 7 1583
感动是毒
感动是毒 2020-11-28 07:36

I have one class.

Class First {

    private Second second;

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


        
相关标签:
7条回答
  • 2020-11-28 07:53

    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
    }
    
    0 讨论(0)
  • 2020-11-28 07:57

    Include this line on top of your test class

    @PrepareForTest({ First.class })
    
    0 讨论(0)
  • 2020-11-28 08:03

    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.

    0 讨论(0)
  • 2020-11-28 08:11

    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();
     }
    
    0 讨论(0)
  • 2020-11-28 08:13

    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.

    0 讨论(0)
  • 2020-11-28 08:13

    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

    0 讨论(0)
提交回复
热议问题