[解決済み] モッキートで発見された未完成のスタッブ
質問
テストの実行中に以下のような例外が発生します。モッキングにMockitoを使用しています。Mockitoのライブラリに記載されているヒントは役に立ちません。
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at com.a.b.DomainTestFactory.myTest(DomainTestFactory.java:355)
E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, you naughty developer!
at a.b.DomainTestFactory.myTest(DomainTestFactory.java:276)
..........
からのテストコード
DomainTestFactory
. 以下のテストを実行すると、例外が表示されます。
@Test
public myTest(){
MyMainModel mainModel = Mockito.mock(MyMainModel.class);
Mockito.when(mainModel.getList()).thenReturn(getSomeList()); // Line 355
}
private List<SomeModel> getSomeList() {
SomeModel model = Mockito.mock(SomeModel.class);
Mockito.when(model.getName()).thenReturn("SomeName"); // Line 276
Mockito.when(model.getAddress()).thenReturn("Address");
return Arrays.asList(model);
}
public class SomeModel extends SomeInputModel{
protected String address;
protected List<SomeClass> properties;
public SomeModel() {
this.Properties = new java.util.ArrayList<SomeClass>();
}
public String getAddress() {
return this.address;
}
}
public class SomeInputModel{
public NetworkInputModel() {
this.Properties = new java.util.ArrayList<SomeClass>();
}
protected String Name;
protected List<SomeClass> properties;
public String getName() {
return this.Name;
}
public void setName(String value) {
this.Name = value;
}
}
解決方法は?
モッキングの中にモッキングを入れ子にしている。 あなたは
getSomeList()
に対するモックを完了させる前に、いくつかのモックを実行します。
MyMainModel
. このようなことをすると、Mockitoは嫌がります。
置き換える
@Test
public myTest(){
MyMainModel mainModel = Mockito.mock(MyMainModel.class);
Mockito.when(mainModel.getList()).thenReturn(getSomeList()); --> Line 355
}
と
@Test
public myTest(){
MyMainModel mainModel = Mockito.mock(MyMainModel.class);
List<SomeModel> someModelList = getSomeList();
Mockito.when(mainModel.getList()).thenReturn(someModelList);
}
この問題を理解するためには、Mockitoの仕組みと、Javaで式や文がどのような順序で評価されるかを知っておく必要があります。
Mockitoはソース・コードを読むことができないので、何をするように要求されているかを理解するために、静的状態に大きく依存します。 モックオブジェクトのメソッドを呼び出すと、Mockitoはその呼び出しの詳細を内部の呼び出しリストに記録します。 その際
when
メソッドは、これらの呼び出しのうち最後のものをリストから読み出し、この呼び出しを
OngoingStubbing
オブジェクトを返します。
行の
Mockito.when(mainModel.getList()).thenReturn(someModelList);
は、Mockitoと次のようなやりとりをします。
-
モックメソッド
mainModel.getList()
が呼び出されます。 -
静的メソッド
when
が呼び出されます。 -
方法
thenReturn
が呼び出されます。OngoingStubbing
オブジェクトを返します。when
メソッドを使用します。
は、その
thenReturn
メソッドで受け取ったモックを
OngoingStubbing
メソッドへの任意の適切な呼び出しを処理するために
getList
を返すメソッドです。
someModelList
.
実は、Mockitoはあなたのコードを見ることができないので、以下のようにモッキングを書くことも可能です。
mainModel.getList();
Mockito.when((List<SomeModel>)null).thenReturn(someModelList);
このスタイルでは、特にこの場合は
null
をキャストする必要がありますが、これはMockitoとの一連のやりとりを生成し、上の行と同じ結果を達成します。
しかし、この行は
Mockito.when(mainModel.getList()).thenReturn(getSomeList());
は、Mockitoと次のようなやりとりをします。
-
モックメソッド
mainModel.getList()
が呼び出されます。 -
静的メソッド
when
が呼び出されます。 -
新しい
mock
のSomeModel
が作成されます(内部getSomeList()
), -
モックメソッド
model.getName()
が呼び出されます。
この時点でMockitoは混乱します。 あなたがモックしているのは
mainModel.getList()
をモック化するように言っているのです。
model.getName()
メソッドを使用します。 Mockitoには、以下のように見えます。
when(mainModel.getList());
// ...
when(model.getName()).thenReturn(...);
にはバカバカしく見える。
Mockito
で何をしているのかがわからないからです。
mainModel.getList()
.
に至っていないことに注意してください。
thenReturn
というのも、JVMはメソッドを呼び出す前に、このメソッドへのパラメータを評価する必要があるからです。 この場合、これは
getSomeList()
メソッドを使用します。
一般に、Mockitoのように静的状態に依存するのは設計上よくない判断です。なぜなら、最小驚嘆の原則に違反するケースにつながるからです。 しかし、Mockitoの設計は、時には驚きをもたらすとしても、明確で表現力豊かなモッキングを可能にします。
最後に、最近のMockitoのバージョンでは、上記のエラーメッセージに1行追加されています。 この追加行は、この質問と同じ状況になっている可能性を示しています。
3: 'thenReturn' 命令が完了する前に、別のモックの挙動をスタブしています。
関連
-
[解決済み】破損したjarファイル
-
[解決済み] StringBuilderをクリアまたは空にするにはどうすればよいですか?重複] [重複] [重複] [重複] [重複] [重複
-
[解決済み] Hide Utility Class Constructor : ユーティリティクラスはパブリックまたはデフォルトコンストラクタを持つべきではありません。
-
[解決済み] Mockitoでvoidメソッドをモックする方法
-
[解決済み] フェイク、モッキング、スタビングの違いとは?
-
[解決済み] Mockitoを使用して特定のメソッドが呼び出されていないことを確認するにはどうすればよいですか?
-
[解決済み] Mockitoは複数回呼び出されたメソッドの引数をキャプチャできますか?
-
[解決済み] Mockitoを使用して、あるメソッドをモックし、他のメソッドをモックしない
-
[解決済み] voidメソッドが例外を投げるかどうかをMockitoがテストする
-
[解決済み] Mockitoで静的メソッドをモックする
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】HTTPステータス 405 - リクエストメソッド「POST」はサポートされていません (Spring MVC)
-
[解決済み】Android Studio クラス org.codehaus.groovy.runtime.InvokerHelper を初期化できませんでした。
-
[解決済み】Doubleはdereferencedできない?
-
[解決済み】Android Studioでタスク :app:compileDebugJavaWithJavac の実行に失敗しました。
-
[解決済み] 解決済み】Javaが「型をインスタンス化できない」というエラーを返す [重複] [重複]
-
[解決済み] メソッドがそのスーパークラスのメソッドをオーバーライドしない
-
[解決済み】メソッド本体がない、またはJavaで抽象的な宣言をする
-
[解決済み】Javaの未処理例外について
-
[解決済み] エラー - trustAnchors パラメータは空であってはなりません。
-
[解決済み] SQLエラー。0, SQLState: 08S01 通信リンクの失敗 [重複]。