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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3162551/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 16:58:51  来源:igfitidea点击:

How do I mock static methods in a class with easymock?

javaunit-testingstatictddeasymock

提问by JavaRocky

Suppose I have a class like so:

假设我有一个这样的类:

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

How do I mock the static method call using easy mock? StaticDude.getGroove().

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

I am using easy mock 3.0

我正在使用简单的模拟 3.0

采纳答案by Ben J

Not sure how to with pure EasyMock, but consider using the PowerMockextensions to EasyMock.

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

It has a lot of cool functions for doing just what you need - https://github.com/jayway/powermock/wiki/MockStatic

它有很多很酷的功能可以做你需要的 - https://github.com/jayway/powermock/wiki/MockStatic

回答by stevebot

Easymock is a testing framework for "for interfaces (and objects through the class extension)" so you can mock a class without an interface. Consider creating an interfaced object with an accessor for your static class and then mock that acessor instead.

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

EDIT: Btw, I wouldn't recommend doing static classes. It is better to have everything interfaced if you are doing TDD.

编辑:顺便说一句,我不建议做静态类。如果你在做 TDD,最好把所有东西都连接起来。

回答by Vivian River

Generally speaking, it is not possible to mock a static method without using some sort of accessor, which seems to defeat the purpose of using a static method. It can be quite frustrating.

一般来说,在不使用某种访问器的情况下模拟静态方法是不可能的,这似乎违背了使用静态方法的目的。这可能非常令人沮丧。

There is one tool that I know of called "TypeMock Isolator" which uses some sort of Satanic Magic to mock static methods, but that tool is quite expensive.

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

The problem is, I know of no way to override a static method. You can't declare it virtual. you can't include it in an interface.

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

Sorry to be a negative nelly.

很抱歉成为一个消极的 nelly。

回答by mocker

Just in Case PowerMock is unavailable for any reason:

以防万一 PowerMock 因任何原因不可用:

You could move the static call to a method, override this method in the instantiation of the tested class in the test class, create a local interface in the test class and use its method in the overidden method:

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

private interface IMocker 
{
    boolean doSomething();
}

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

...

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

...

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

回答by TheBakker

Adding an exemple on how to implements static mock along regular mock of injected classes with EasyMock / PowerMock, since the linked exemple only shows static mock.

添加一个关于如何使用 EasyMock / PowerMock 沿着注入类的常规模拟实现静态模拟的示例,因为链接的示例仅显示静态模拟。

And with the PowerMockRunnerthe @Mockservices are not wired on the @TestSubjectservice to test.

并与PowerMockRunner@Mock服务没有有线的@TestSubject服务测试。

Let say we have a service we want to test, ServiceOne :

假设我们有一个要测试的服务 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);
    }
}

Which calls another service that we will want to mock, ServiceTwo :

它调用另一个我们想要模拟的服务 ServiceTwo :

import org.springframework.stereotype.Service;

@Service
public class ServiceTwo {

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

And which calls a final class static method, ServiceUtils :

并调用最终类静态方法 ServiceUtils :

public final class ServiceUtils {

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

When calling ServiceOne.methodToTest()we get "+ServiceTwoReturn"as a return.

打电话时,ServiceOne.methodToTest()我们得到"+ServiceTwoReturn"作为回报。



Junit Test with EasyMock, mocking only the injected ServiceTwo Spring service :

使用 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);
    }
}


Junit Test with EasyMock & PowerMock, mocking the injected ServiceTwo Spring service but also the final class and its Static method :

使用 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);
    }
}