如何使用easymock在类中模拟静态方法?

时间:2010-07-02 00:27:01

标签: java unit-testing static tdd easymock

假设我有一个这样的类:

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

如何使用easy mock模拟静态方法调用? StaticDude.getGroove()

我正在使用easy mock 3.0

5 个答案:

答案 0 :(得分:25)

不确定如何使用纯EasyMock,但请考虑使用EasyMock的PowerMock扩展名。

它有很多很酷的功能可以满足您的需求 - https://github.com/jayway/powermock/wiki/MockStatic

答案 1 :(得分:11)

Easymock是“用于接口(以及通过类扩展的对象)”的测试框架,因此您可以在没有接口的情况下模拟类。考虑创建一个带有静态类访问器的接口对象,然后模拟该访问器。

编辑:顺便说一下,我不建议做静态类。如果您正在进行TDD,最好将所有内容都连接起来。

答案 2 :(得分:9)

以防万一PowerMock因任何原因无法使用:

您可以将静态调用移动到方法,在测试类中测试类的实例化中覆盖此方法,在测试类中创建本地接口并在覆盖方法中使用其方法:

private interface IMocker 
{
    boolean doSomething();
}

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

...

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

...

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

答案 3 :(得分:4)

一般来说,如果不使用某种访问器,就不可能模拟静态方法,这似乎无法使用静态方法。这可能非常令人沮丧。

我知道有一种名为“TypeMock Isolator”的工具,它使用某种魔法魔法来模拟静态方法,但该工具非常昂贵。

问题是,我知道无法覆盖静态方法。你不能声明它是虚拟的。你不能把它包含在一个界面中。

很抱歉成为负面的人。

答案 4 :(得分:1)

添加一个关于如何使用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进行Junit测试& PowerMock,模拟注入的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);
    }
}