私は次のようなクラスを持っています:
public class A {
public A(String test) {
bla bla bla
}
public String check() {
bla bla bla
}
}
コンストラクターA(String test)
およびcheck()
のロジックは、私がモックしようとしているものです。次のような呼び出しが必要です:new A($$$any string$$$).check()
はダミー文字列"test"
を返します。
私は試した:
A a = mock(A.class);
when(a.check()).thenReturn("test");
String test = a.check(); // to this point, everything works. test shows as "tests"
whenNew(A.class).withArguments(Matchers.anyString()).thenReturn(rk);
// also tried:
//whenNew(A.class).withParameterTypes(String.class).withArguments(Matchers.anyString()).thenReturn(rk);
new A("random string").check(); // this doesn't work
しかし、機能していないようです。 new A($$$any string$$$).check()
は、A
のモックされたオブジェクトをフェッチする代わりに、コンストラクターロジックを引き続き使用します。
あなたが投稿したコードは、MockitoとPowermockitoの最新バージョンで動作します。たぶん、あなたはAを準備していませんか?これを試して:
A.Java
public class A {
private final String test;
public A(String test) {
this.test = test;
}
public String check() {
return "checked " + this.test;
}
}
MockA.Java
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest(A.class)
public class MockA {
@Test
public void test_not_mocked() throws Throwable {
assertThat(new A("random string").check(), equalTo("checked random string"));
}
@Test
public void test_mocked() throws Throwable {
A a = mock(A.class);
when(a.check()).thenReturn("test");
PowerMockito.whenNew(A.class).withArguments(Mockito.anyString()).thenReturn(a);
assertThat(new A("random string").check(), equalTo("test"));
}
}
どちらのテストも、mockito 1.9.0、powermockito 1.4.12、junit 4.8.2に合格する必要があります
私の知る限り、コンストラクターをmockitoでモックすることはできません。メソッドのみです。しかし、Mockitoのgoogleコードページのウィキによると、クラスの新しいインスタンスを返すメソッドをクラスに作成することで、コンストラクターの動作をモックする方法があります。その後、そのメソッドをモックアウトできます。以下は Mockito wikiからの直接の抜粋 です:
パターン1-オブジェクト作成に1行のメソッドを使用する
パターン1(MyClassというクラスをテストする)を使用するには、次のような呼び出しを置き換えます。
Foo foo = new Foo( a, b, c );
と
Foo foo = makeFoo( a, b, c );
そして、1行のメソッドを書きます
Foo makeFoo( A a, B b, C c ) { return new Foo( a, b, c ); }
メソッドにロジックを含めないことが重要です。オブジェクトを作成する1行だけです。この理由は、メソッド自体が単体テストされることは決してないからです。
クラスをテストするとき、テストするオブジェクトは実際にはモックを返し、このメソッドがオーバーライドされてモックトスパイになります。したがって、テストしているのはクラス自体ではなく、ごくわずかに修正されたバージョンです。
テストクラスには次のようなメンバーが含まれる場合があります
@Mock private Foo mockFoo; private MyClass toTest = spy(new MyClass());
最後に、テストメソッド内でmakeFooの呼び出しを次のような行でモックアウトします。
doReturn( mockFoo ) .when( toTest ) .makeFoo( any( A.class ), any( B.class ), any( C.class ));
コンストラクターに渡される引数を確認する場合は、any()よりも具体的なマッチャーを使用できます。
あなたのクラスのモックされたオブジェクトを返したいだけなら、これはあなたのために働くはずだと思います。いずれにせよ、モックオブジェクト作成の詳細については、こちらをご覧ください。
Powermockを使用しない場合.... Ben Glasserの回答に基づいた以下の例を参照してください。
元のクラス:
public class AClazz {
public void updateObject(CClazz cClazzObj) {
log.debug("Bundler set.");
cClazzObj.setBundler(new BClazz(cClazzObj, 10));
}
}
変更されたクラス:
@Slf4j
public class AClazz {
public void updateObject(CClazz cClazzObj) {
log.debug("Bundler set.");
cClazzObj.setBundler(getBObject(cClazzObj, 10));
}
protected BClazz getBObject(CClazz cClazzObj, int i) {
return new BClazz(cClazzObj, 10);
}
}
テストクラス
public class AClazzTest {
@InjectMocks
@Spy
private AClazz aClazzObj;
@Mock
private CClazz cClazzObj;
@Mock
private BClazz bClassObj;
@Before
public void setUp() throws Exception {
Mockito.doReturn(bClassObj)
.when(aClazzObj)
.getBObject(Mockito.eq(cClazzObj), Mockito.anyInt());
}
@Test
public void testConfigStrategy() {
aClazzObj.updateObject(cClazzObj);
Mockito.verify(cClazzObj, Mockito.times(1)).setBundler(bClassObj);
}
}
Mockitoには、final、static、およびprivateメソッドのテストに制限があります。
jMockitテストライブラリを使用すると、以下のように非常に簡単で簡単な作業をいくつか実行できます。
Java.io.Fileクラスのモックコンストラクター:
new MockUp<File>(){
@Mock
public void $init(String pathname){
System.out.println(pathname);
// or do whatever you want
}
};
静的メソッドのモック: