web-dev-qa-db-ja.com

Mockito:@Autowiredのプライベートフィールドに実際のオブジェクトを挿入する

Mockitoの@Mockおよび@InjectMocksアノテーションを使用して、Springの@Autowiredアノテーションが付けられたプライベートフィールドに依存関係を注入しています。

@RunWith(MockitoJUnitRunner.class)
public class DemoTest {
    @Mock
    private SomeService service;

    @InjectMocks
    private Demo demo;

    /* ... */
}

そして

public class Demo {

    @Autowired
    private SomeService service;

    /* ... */
}

今、私はrealオブジェクトをプライベートな@Autowiredフィールド(セッターなし)に注入したいと思います。これは可能ですか、またはメカニズムはモックの注入のみに制限されていますか?

159
user2286693

@Spyアノテーションを使用する

@RunWith(MockitoJUnitRunner.class)
public class DemoTest {
    @Spy
    private SomeService service = new RealServiceImpl();

    @InjectMocks
    private Demo demo;

    /* ... */
}

Mockitoは、@Mockまたは@Spy注釈を持つすべてのフィールドを、@InjectMocks注釈が付けられたインスタンスに注入される潜在的な候補と見なします。上記の場合、'RealServiceImpl'インスタンスは「デモ」に挿入されます

詳細については

Mockito-home

@ Spy

@ Mock

248
Dev Blanked

Add to @Dev Blanked answerでは、Springによって作成された既存のBeanを使用する場合、コードを次のように変更できます。

@RunWith(MockitoJUnitRunner.class)
public class DemoTest {

    @Inject
    private ApplicationContext ctx;

    @Spy
    private SomeService service;

    @InjectMocks
    private Demo demo;

    @Before
    public void setUp(){
        service = ctx.getBean(SomeService.class);
    }

    /* ... */
}

この方法では、テストを機能させるためだけにコードを変更する(別のコンストラクターを追加する)必要はありません。

16
Yoaz Menda

MockitoはDIフレームワークではなく、DIフレームワークでさえフィールドインジェクションよりもコンストラクタインジェクションを推奨しています。
したがって、テストするクラスの依存関係を設定するコンストラクタを宣言するだけです。

@Mock
private SomeService serviceMock;

private Demo demo;

/* ... */
@BeforeEach
public void beforeEach(){
   demo = new Demo(serviceMock);
}

一般的な場合にMockito spyを使用することは、ひどいアドバイスです。それはテストクラスを真っ直ぐではなく脆くし、エラーを起こしやすくします:本当にm笑されるものは何ですか?実際にテストされるのは何ですか?
@InjectMocksおよび@Spyも、クラスの肥大化とクラスの責任の混在を助長するため、全体的な設計を損ないます。
ください spy() javadocを読んでください 盲目的に使用する前に(強調は私のものではありません):

実オブジェクトのスパイを作成します。スパイは、スタブ化されていない限り、realメソッドを呼び出します。たとえば、レガシーコードを扱う場合は、実際のスパイを慎重に、ときどき使用する必要があります。

いつものようにpartial mock warningを読みます:オブジェクト指向プログラミングは、複雑さを個別の特定のSRPyオブジェクトに分割することにより、複雑さに取り組みます。部分モックはこのパラダイムにどのように適合しますか?そうではありません...部分的なモックは、通常、複雑さが同じオブジェクトの別のメソッドに移動したことを意味します。ほとんどの場合、これはアプリケーションの設計方法ではありません。

ただし、部分モックが便利な場合はまれです:簡単に変更できないコードを処理する(サードパーティのインターフェイス、レガシーコードの暫定的なリファクタリングなど)ただし、新しいテスト駆動型のウェルモックには部分モックを使用しません。設計されたコード。

0
davidxxx