Mockito、JUnitとSpring
質問
私は今日、Mockitoについて学び始めました。私はいくつかの簡単なテスト(JUnitを使用して、以下を参照)を書きましたが、私はSpringの管理されたビーン内でモックオブジェクトをどのように使用できるかが分かりません。というのは ベストプラクティス は何ですか?モック化された依存関係をどのように自分のBeanに注入すればよいですか?
まで省略可能です。 私の質問に戻って .
まず、私が学んだこと。 これは非常に良い記事です モックはスタブではない という記事で、基本的なことが説明されています(Mockのチェックは 動作検証 ではなく 状態検証 ). それから、ここに良い例があります モッキート とこちら mockitoでより簡単にモック化 . Mockitoのモックオブジェクトが、いずれも モック と スタブ .
ここで モッキート そして、ここでは マッチャー で、より多くの例を見ることができます。
このテストは
@Test
public void testReal(){
List<String> mockedList = mock(List.class);
//stubbing
//when(mockedList.get(0)).thenReturn("first");
mockedList.get(anyInt());
OngoingStubbing<String> stub= when(null);
stub.thenReturn("first");
//String res = mockedList.get(0);
//System.out.println(res);
//you can also verify using argument matcher
//verify(mockedList).get(anyInt());
verify(mockedList);
mockedList.get(anyInt());
}
はうまく動作します。
私の質問に戻ります。
ここで
MockitoのモックをSpringビーンに注入する
誰かがSpringを使おうとして
ReflectionTestUtils.setField()
を使おうとするが、ここで
Springの統合テスト、モックオブジェクトの作成
を推奨しています。
変更
Springのコンテキストを変更することを推奨しています。
私は最後の2つのリンクを本当に理解していませんでした... 誰か、SpringがMockitoとどのような問題があるのか、説明してもらえますか?このソリューションのどこが問題なのでしょうか?
@InjectMocks
private MyTestObject testObject
@Mock
private MyDependentObject mockedObject
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
https://stackoverflow.com/a/8742745/1137529
EDIT
: 私は本当に明確ではなかった。私は私の自己を明確にするためにコードの3つの例を提供します。
私たちはメソッドを持つビーンHelloWorldを持っているとします。
printHello()
とメソッドを持つビーンHelloFacadeがあるとします。
sayHello
で、HelloWorld のメソッドへの呼び出しを転送します。
printHello()
.
最初の例は、Springのコンテキストを使用し、カスタムランナーなしで、依存性注入(DI)のためにReflectionTestUtilsを使用するものです。
public class Hello1Test {
private ApplicationContext ctx;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
this.ctx = new ClassPathXmlApplicationContext("META-INF/spring/ServicesImplContext.xml");
}
@Test
public void testHelloFacade() {
HelloFacade obj = (HelloFacade) ctx.getBean(HelloFacadeImpl.class);
HelloWorld mock = mock(HelloWorld.class);
doNothing().when(mock).printHello();
ReflectionTestUtils.setField(obj, "hello", mock);
obj.sayHello();
verify(mock, times(1)).printHello();
}
}
Noam が指摘したように、明示的に
MockitoAnnotations.initMocks(this);
. また、この例ではSpringのコンテキストを使用しないことにします。
@RunWith(MockitoJUnitRunner.class)
public class Hello1aTest {
@InjectMocks
private HelloFacade obj = new HelloFacadeImpl();
@Mock
private HelloWorld mock;
@Test
public void testHelloFacade() {
doNothing().when(mock).printHello();
obj.sayHello();
}
}
別の方法として
public class Hello1aTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@InjectMocks
private HelloFacadeImpl obj;
@Mock
private HelloWorld mock;
@Test
public void testHelloFacade() {
doNothing().when(mock).printHello();
obj.sayHello();
}
}
前の例では、HelloFacade はインターフェースなので、手動で HelloFacadeImpl をインスタンス化し、HelloFacade に代入しなければなりませんでしたが、この例では、HelloFacadeImpl を宣言するだけで、木人がインスタンス化してくれます。この例では、HelloFacadeImpl を宣言するだけで、Mokito がそれをインスタンス化してくれます。しかし、この方法の欠点は、ユニット・アンダー・テストがインターフェイスではなく、impl-classになってしまうことです。
どうすればいいのか?
正直なところ、私はあなたの質問を本当に理解しているかどうかわからない :P 私はあなたの元の質問から得たものから、私ができる限り明確にしようとします。
まず、ほとんどの場合、Springについて何の心配もする必要はありません。 ユニットテストを書くのにSpringが関与する必要はほとんどありません。 通常の場合、単体テストでテスト対象のシステム(SUT)をインスタンス化し、SUTの依存関係をテストに注入すればよいのです。 依存関係は通常、モック/スタブです。
あなたのオリジナルの提案された方法、および例2、3は、まさに私が上記で説明したことを行っています。
稀なケース(統合テストや特別なユニットテストのような)では、Springアプリコンテキストを作成し、アプリコンテキストからSUTを取得する必要があります。 そのような場合、私はあなたができると信じています。
1) SUTをSpringアプリコンテキストに作成し、それへの参照を取得し、モックを注入する。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("test-app-ctx.xml")
public class FooTest {
@Autowired
@InjectMocks
TestTarget sut;
@Mock
Foo mockFoo;
@Before
/* Initialized mocks */
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test
public void someTest() {
// ....
}
}
または
2) リンクに記載されている方法に従ってください Springの統合テスト、モックオブジェクトの作成 . この方法は、Springのアプリコンテキストでモックを作成し、アプリCTXからモックオブジェクトを取得してスタブや検証を行う方法です。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("test-app-ctx.xml")
public class FooTest {
@Autowired
TestTarget sut;
@Autowired
Foo mockFoo;
@Test
public void someTest() {
// ....
}
}
どちらの方法でも動作するはずです。 主な違いは、前者はspringのライフサイクルなどを経た後に依存関係を注入する(例:Beanの初期化)のに対し、後者は事前に注入することです。 例えば、SUTがspringのInitializingBeanを実装しており、初期化ルーチンに依存関係が含まれている場合、この2つのアプローチの違いが分かると思います。 この2つのアプローチは、自分が何をやっているのかが分かっていれば、どちらが正しいということはないと思います。
補足ですが、@Mock、@Inject、MocktoJunitRunnerなどは、Mockitoを使う上では不要なものばかりです。 これらは、Mockito.mock(Foo.class)とセッターの起動を省くためのユーティリティに過ぎません。
関連
-
Eclipseは、ポップアップA Java Exception has occurred.を実行し、エラーException in threadの解決策を報告します。
-
メモ帳でJavaプログラムをコンパイルして実行すると、Could not find or load main class ...というエラーが表示される。解決方法
-
Jsoup-Crawlingの動作
-
[解決済み] JavaにおけるHashMapとHashtableの違いは何ですか?
-
[解決済み] Javaにおけるpublic、protected、package-private、privateの違いは何ですか?
-
[解決済み] serialVersionUIDとは何ですか、またなぜそれを使用する必要がありますか?
-
[解決済み] JUnit 4のテストで、ある例外が投げられたことをどのように断言しますか?
-
[解決済み] 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 実装 サイバーパンク風ボタン
おすすめ
-
Collections.sortがdoubleでソートできない問題を完璧に解決する。
-
スレッド "main" での例外 java.lang.ArrayIndexOutOfBoundsException:5 エラー
-
シェルコマンドやスクリプトのJavaコール
-
Javaがリソースリークに遭遇した:'input'が閉じない 解決方法
-
Server Tomcat v9.0 Server at localhost の起動に失敗しました。
-
Javaがエラーで実行される、選択が起動できない、最近起動したものがない
-
git pull appears現在のブランチに対するトラッキング情報がありません。
-
java 365*1000*60*60*24 計算問題
-
switch case文のcaseの後の列挙定数は列挙型なし
-
linux ant Resolve error: main class not found or couldn't be loaded org.apache.tools.ant.launcher.