50

クラスが1つあります。

Class First {

    private Second second;

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

    ... // some other methods
}

クラスFirstのパブリックメソッドの単体テストを書きたい。Secondクラスのコンストラクターの実行を避けたい。

これは私がしました:

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

それはまだクラスSecondのコンストラクターを呼び出しています。どうすればそれを回避できますか?

4

7 に答える 7

72

PowerMockitoを使用できます

例を参照してください。

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

しかし、リファクタリングはより良い決定です。

于 2012-06-26T19:55:12.060 に答える
32

繰り返しますが、単体テストの問題は、new演算子を使用してオブジェクトを手動で作成することから生じます。Second代わりに、すでに作成されているものを渡すことを検討してください。

class First {

  private Second second;

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

  // some other methods...
}

これはAPIの大幅な書き直しを意味する可能性があることは知っていますが、他の方法はありません。また、このクラスには意味がありません。

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

まず第一に、Mockitoはメソッドのみをモックでき、コンストラクターはモックできません。第二に、コンストラクターをモックできたとしても、作成したばかりのオブジェクトのコンストラクターをモックしているので、そのオブジェクトに対して実際には何もしていません。

于 2012-06-26T18:58:20.410 に答える
17

PowerMockitoAPIを使用してこの機能をモックするコードは次のとおりです。

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

Powermockito runnerを使用する必要があり、powermock APIによってモックする必要がある必要なテストクラス(コンマ区切り)を追加する必要があります。

@RunWith(PowerMockRunner.class)
@PrepareForTest({First.class,Second.class})
class TestClassName{
    // your testing code
}
于 2015-11-20T09:18:27.270 に答える
5

「パターン2-「ファクトリーヘルパーパターン」」を使用しました

パターン2-ファクトリーヘルパーパターン

このパターンが機能しない1つのケースは、MyClassがfinalである場合です。Mockitoフレームワークのほとんどは、最終クラスでは特にうまく機能しません。これには、spy()の使用が含まれます。もう1つのケースは、MyClassがどこかでgetClass()を使用し、結果の値がMyClassである必要がある場合です。スパイのクラスは実際には元のクラスのMockitoで生成されたサブクラスであるため、これは機能しません。

これらのいずれの場合でも、次のように、もう少し堅牢なファクトリヘルパーパターンが必要になります。

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

したがって、テスト専用の特別なコンストラクターがあり、追加の引数があります。これは、テストするオブジェクトを作成するときに、テストクラスから使用されます。テストクラスでは、作成するオブジェクトだけでなく、FactoryHelperクラスもモックします。

@Mock private MyClass.FactoryHelper mockFactoryHelper;
@Mock private Foo mockFoo;
private MyClass toTest;

そして、あなたはそれをこのように使うことができます

toTest = new MyClass( x, y, mockFactoryHelper ); 
when( mockFactoryHelper.makeFoo( 
  any( A.class ), any( B.class ), any( C.class )))
  .thenReturn( mockFoo ); 

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

于 2014-01-21T15:56:09.750 に答える
4

Mockitoはコンストラクターをモックできるようになりました(バージョン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();
 }
于 2020-09-30T14:51:08.590 に答える
1

mockitoを使ってコンストラクターをモックすることはできないと思います。代わりに、次のアプローチをお勧めします

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
}

そして、テストのために:

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);
    }
}
于 2018-03-06T16:21:48.453 に答える
-1

テストクラスの上にこの行を含めます

@PrepareForTest({ First.class })
于 2020-03-23T23:52:16.133 に答える