web-dev-qa-db-ja.com

JMockitを使用してテスト中のクラスのプライベートメソッドをモックする

テスト中のクラスのプライベートメソッドをモックしたいのですが、メソッドが呼び出された後にメソッドが最初に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;
                }
            };

        }
    };
13
Varun

Expectations(またはStrictExpectations)の使用

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の使用(JMockit 1.23で非推奨)

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();
}
13
Rogério

これは私にとってはうまくいきます:-

        new MockUp<ClassToTest>() {
            @Mock
            boolean methodToMock(int value) {
                return true;
            }
        };
11
Kaushik

ここでは、モック動作でテストクラスの特定のメソッドをオーバーライドできます。

以下のコードの場合:

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;
            }
        };

        ....    

    }
}
1
Amit Kaneria