web-dev-qa-db-ja.com

クラスの静的メソッドをeasymockでモックするにはどうすればよいですか?

次のようなクラスがあるとします:

_public class StaticDude{
    public static Object getGroove() {
        // ... some complex logic which returns an object
    };
}
_

簡単なモックを使用して静的メソッド呼び出しをモックするにはどうすればよいですか? StaticDude.getGroove()

簡単なモック3.0を使用しています

29
JavaRocky

純粋なEasyMockの使い方はわかりませんが、EasyMockの PowerMock 拡張機能の使用を検討してください。

必要なことだけを行うためのクールな機能がたくさんあります- https://github.com/jayway/powermock/wiki/MockStatic

25
Ben J

Easymockは、「インターフェイス(およびクラス拡張を介したオブジェクト)」のテストフレームワークであるため、インターフェイスなしでクラスをモックできます。静的クラスのアクセサを使用してインターフェイスオブジェクトを作成し、代わりにそのアクセサをモックすることを検討してください。

編集:ところで、私は静的クラスを行うことをお勧めしません。 TDDを実行している場合は、すべてがインターフェイスされている方が良いです。

11
stevebot

念のため、PowerMockは何らかの理由で使用できません。

静的呼び出しをメソッドに移動し、テストクラスのテスト対象クラスのインスタンス化でこのメソッドをオーバーライドし、テストクラスでローカルインターフェイスを作成し、オーバーライドされたメソッドでそのメソッドを使用できます。

private interface IMocker 
{
    boolean doSomething();
}

IMocker imocker = EasyMock.createMock(IMocker.class);

...

@Override
void doSomething()
{
     imocker.doSomething();
}

...

EasyMock.expect(imocker.doSomething()).andReturn(true);
9
mocker

一般的に言って、ある種のアクセサーを使用せずに静的メソッドをモックすることはできません。これは、静的メソッドを使用する目的に反するようです。かなりイライラすることがあります。

私が知っている「TypeMock Isolator」というツールは、ある種の悪魔の魔法を使用して静的メソッドをモックするツールですが、そのツールは非常に高価です。

問題は、静的メソッドをオーバーライドする方法がないことです。仮想と宣言することはできません。インターフェイスに含めることはできません。

ネガティブなネリーになってすみません。

リンクされた例は静的モックのみを表示するため、EasyMock/PowerMockを使用して、注入されたクラスの通常のモックに沿って静的モックを実装する方法の例を追加します。

PowerMockRunnerを使用すると、_@Mock_サービスはテストする_@TestSubject_サービスに接続されません。

テストするサービスServiceOneがあるとします。

_import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ServiceOne {

    @Autowired
    private ServiceTwo serviceTwo;

    public String methodToTest() {
        String returnServ2 = serviceTwo.methodToMock();
        return ServiceUtils.addPlus(returnServ2);
    }
}
_

これは、モックしたい別のサービスServiceTwoを呼び出します。

_import org.springframework.stereotype.Service;

@Service
public class ServiceTwo {

    public String methodToMock() {
        return "ServiceTwoReturn";
    }
}
_

そして、最終クラスの静的メソッドServiceUtilsを呼び出します。

_public final class ServiceUtils {

    public static String addPlus(String pParam) {
        return "+" + pParam;
    }
}
_

ServiceOne.methodToTest()を呼び出すと、戻り値として_"+ServiceTwoReturn"_が返されます。


EasyMockによるJunitテスト、注入されたServiceTwo Springサービスのみをモック:

_import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;

import org.easymock.EasyMockRunner;
import org.easymock.Mock;
import org.easymock.TestSubject;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(EasyMockRunner.class)
public class ExempleTest {

    @TestSubject
    private ServiceOne serviceToTest = new ServiceOne();

    @Mock
    private ServiceTwo serviceMocked;

    @Test
    public void testMethodToTest() {
        String mockedReturn = "return2";

        expect(serviceMocked.methodToMock()).andReturn(mockedReturn);
        replay(serviceMocked);

        String result = serviceToTest.methodToTest();

        verify(serviceMocked);

        assertEquals("+" + mockedReturn, result);
    }
}
_

EasyMock PowerMockを使用したJunitテスト、注入されたServiceTwo Springサービスをモックしますが、最終クラスとその静的メソッドもモックします:

_import static org.easymock.EasyMock.expect;
import static org.junit.Assert.assertEquals;
import static org.powermock.api.easymock.PowerMock.createMock;
import static org.powermock.api.easymock.PowerMock.mockStatic;
import static org.powermock.reflect.Whitebox.setInternalState;

import org.easymock.Mock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(ServiceUtils.class)
public class ExempleTest {

    private ServiceOne serviceToTest;

    private ServiceTwo serviceMocked;

    @Before
    public void setUp() {
        serviceToTest = new ServiceOne();
        serviceMocked = createMock(ServiceTwo.class);
        // This will wire the serviced mocked into the service to test
        setInternalState(serviceToTest, serviceMocked);
        mockStatic(ServiceUtils.class);
    }

    @Test
    public void testMethodToTest() {
        String mockedReturn = "return2";
        String mockedStaticReturn = "returnStatic";

        expect(serviceMocked.methodToMock()).andReturn(mockedReturn);
        expect(ServiceUtils.addPlus(mockedReturn)).andReturn(mockedStaticReturn);
        PowerMock.replayAll();

        String result = serviceToTest.methodToTest();

        PowerMock.verifyAll();

        assertEquals(mockedStaticReturn, result);
    }
}
_
1
TheBakker