2

2 つの Map フィールドを持つ抽象クラスがあります。単体テストのために、AbstractClass のサブクラスのオブジェクトをモックして注入したいと考えています。もう1つはあまり気にしませんが、セッターがあります。

public abstract class AbstractClass {
    private Map<String, Object> mapToMock;
    private Map<String, Object> dontMockMe;

    private void setDontMockMe(Map<String, Object> map) {
        dontMockMe = map;
    }
}

@InjectMocks を使用すると、コンストラクター、セッター、フィールドの順に自動的に注入しようとします。タイプをチェックして、これらの各場所に注入できるかどうかをチェックし、複数のタイプの可能性がある場合は名前を付けます。私のモックされた mapToMock は実際にはセッターを介して dontMockMe に注入されるため、これはうまくいきません。この抽象クラスを編集できません。セッター注入を回避する方法はありますか? 前もって感謝します!

4

1 に答える 1

3

これは、Mockito インジェクションが現在設計されている方法では自動インジェクションが機能しない、まれなケースです。また、同じタイプのフィールドが複数ある場合、Mockito にはいくつかの欠点があります。


なぜこれが機能しないのかを理解するために、Mockito がインジェクションを実行する方法を少し掘り下げてみましょう。

  1. コンストラクター注入を介して依存関係を注入しようとします。成功した場合、最終的な副作用から新しく作成されたインスタンスを保護するために、次の手順を試行しません。

  2. 次に、コンストラクター インジェクションが発生しなかった場合(arg コンストラクターがない、またはオブジェクトが既にインスタンス化されている)、Mockito はモックとセッターの間の一致を探します。ただし、それが自動的に行われるようにするには、いくつかの選択を行う必要があります。

    1. 型のモックのみがあり、型Aを持つセッターが 1 つしかない場合A、セッター インジェクションが発生します。

    2. 複数のモックまたは型のセッターがある場合、型とモックの名前 (通常はフィールド名)Aを使用して一致を見つけようとします。@Mock一致が見つかった場合、注入が行われます。

  3. 次に、注入するモックがまだ残っている場合は、 setter と同じアルゴリズムを使用して、フィールド注入が発生する可能性があります。

    1. 型のモックのみがあり、型Aを持つフィールドが 1 つしかない場合A、フィールド インジェクションが発生します。

    2. 複数のモックまたはタイプのフィールドがある場合、タイプとモックの名前 (通常はフィールド名)Aを使用して一致を見つけようとします。@Mock一致が見つかった場合、注入が行われます。


現時点では、おそらく 1 つのモックしか利用できないため、コードはステージ 2.1 でスタックしています。

Mockito の現在の実装では真に洗練されたソリューションはありません。インジェクション コードを自分で作成する必要があります。インジェクションが複雑すぎたり奇妙だったりする場合は、それを書き出す必要があります。このボイラープレート コードを書くことは、実際には現在の設計に疑問を呈するための最良のツールです。

Mockito インジェクションは、シンプルでストレートなデザイン向けに設計されています。

私の意見では、私は間違っていると思います:

  1. Map所有していない型であるをモックすることは、多くの問題を引き起こす可能性があります。
  2. テストされたオブジェクトの単一のマップのみをモックすることは、テストがテストされたオブジェクトの内部動作について知りすぎていることを意味します。

コードをリファクタリングして共同作業者を出現させると、設計にメリットがあります。明確な依存関係/コラボレーターがあれば、インジェクションもより明確になります。また、テストは、実装がどのように行われるかではなく、共同作業者との相互作用をアサートすることに焦点を当てる必要があります。データは、特定の入力に対する結果としてのみテストする必要があります。

于 2013-07-24T11:27:28.050 に答える