テスト中のクラスのプライベートメソッドをモックしたいのですが、メソッドが呼び出された後にメソッドが最初に2回falseを返し、その後falseが返されます。これが私が試したコードです。これはテストされているクラスです
public class ClassToTest
{
public void methodToTest()
{
Integer integerInstance = new Integer(0);
boolean returnValue= methodToMock(integerInstance);
if(returnValue)
{
System.out.println("methodToMock returned true");
}
else
{
System.out.println("methodToMock returned true");
}
System.out.println();
}
private boolean methodToMock(int value)
{
return true;
}
}
テストクラス
import org.junit.Test;
import static mockit.Deencapsulation.*;
import mockit.*;
public class TestAClass
{
@Tested ClassToTest classToTestInstance;
@Test
public void test1()
{
new NonStrictExpectations(classToTestInstance)
{
{
invoke(classToTestInstance, "methodToMock", anyInt);
returns(false);
times = 2;
invoke(classToTestInstance, "methodToMock", anyInt);
returns(true);
times = 1;
}
};
classToTestInstance.methodToTest();
classToTestInstance.methodToTest();
classToTestInstance.methodToTest();
}
}
希望する結果を得るためにこれを行いました
final StringBuffer count = new StringBuffer("0");
new NonStrictExpectations(classToTestInstance)
{
{
invoke(classToTestInstance, "methodToMock", anyInt);
result= new Delegate()
{
boolean methodToMock(int value)
{
count.replace(0, count.length(), Integer.valueOf(Integer.valueOf(count.toString())+1).toString());
if(Integer.valueOf(count.toString())==3)
{
return true;
}
return false;
}
};
}
};
ExpectationsとDeencapsulation.invoke()を組み合わせて使用すると、テストしたオブジェクトを部分的にモックできます。
import org.junit.Test;
import static mockit.Deencapsulation.*;
import mockit.*;
public class TestAClass
{
public static class ClassToTest
{
public void methodToTest()
{
boolean returnValue = methodToMock(0);
System.out.println("methodToMock returned " + returnValue);
}
private boolean methodToMock(int value) { return true; }
}
@Tested ClassToTest classToTestInstance;
@Test
public void partiallyMockTestedClass() {
new Expectations(classToTestInstance) {{
invoke(classToTestInstance, "methodToMock", anyInt);
result = false;
times = 2;
}};
classToTestInstance.methodToTest();
classToTestInstance.methodToTest();
classToTestInstance.methodToTest();
}
}
上記のテストは以下を出力します:
methodToMock returned false
methodToMock returned false
methodToMock returned true
もちろん、一般に、private
メソッドのモックは避けなければなりません。そうは言っても、実際にはisを使用すると便利な場合があります。通常、重要なことを行うプライベートメソッドがあり、別のテストで既にテストされている場合です。このような場合、2番目のテストでそのプライベートメソッドをモックすること(異なるパブリックメソッドまたは同じパブリックメソッドを介する別のパスのいずれか)は、必要な入力/条件を設定するよりもはるかに簡単です。
NonStrictExpectationsを使用してテストを記述するのも同じくらい簡単です(同じ非厳密な期待値が記録されたtwiceが最初の記録を上書きして、OPによる元の試みが機能しなかっただけです)。
@Test
public void partiallyMockTestedClass() {
new NonStrictExpectations(classToTestInstance) {{
invoke(classToTestInstance, "methodToMock", anyInt);
returns(false, false, true);
}};
classToTestInstance.methodToTest();
classToTestInstance.methodToTest();
classToTestInstance.methodToTest();
}
さらに柔軟性が必要な場合は、常にDelegate
ベースの結果を記録できます。
@Test
public void partiallyMockTestedClass() {
new NonStrictExpectations(classToTestInstance) {{
invoke(classToTestInstance, "methodToMock", anyInt);
result = new Delegate() {
boolean delegate() {
boolean nextValue = ...choose next return value somehow...
return nextValue;
}
}
}};
classToTestInstance.methodToTest();
classToTestInstance.methodToTest();
classToTestInstance.methodToTest();
}
これは私にとってはうまくいきます:-
new MockUp<ClassToTest>() {
@Mock
boolean methodToMock(int value) {
return true;
}
};
ここでは、モック動作でテストクラスの特定のメソッドをオーバーライドできます。
以下のコードの場合:
public class ClassToTest
{
public void methodToTest()
{
Integer integerInstance = new Integer(0);
boolean returnValue= methodToMock(integerInstance);
if(returnValue)
{
System.out.println("methodToMock returned true");
}
else
{
System.out.println("methodToMock returned true");
}
System.out.println();
}
private boolean methodToMock(int value)
{
return true;
}
}
テストクラスは次のようになります。
public class ClassToTestTest{
@Test
public void testMethodToTest(){
new Mockup<ClassToTest>(){
@Mock
private boolean methodToMock(int value){
return true;
}
};
....
}
}