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

发布于 2024-09-07 21:27:06 字数 269 浏览 6 评论 0原文

假设我有一个像这样的类:

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

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

我正在使用 Easy Mock 3.0

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().

I am using easy mock 3.0

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

遇到 2024-09-14 21:27:06

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

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

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

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

终弃我 2024-09-14 21:27:06

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

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

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.

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

回心转意 2024-09-14 21:27:06

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

您可以将静态调用移至某个方法,在测试类中的被测试类的实例化中重写此方法,在测试类中创建本地接口并在重写中使用其方法方法:

private interface IMocker 
{
    boolean doSomething();
}

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

...

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

...

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

Just in Case PowerMock is unavailable for any reason:

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);
偏爱自由 2024-09-14 21:27:06

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

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

问题是,我不知道如何重写静态方法。您不能将其声明为虚拟的。您不能将其包含在界面中。

很抱歉成为一个消极的内莉。

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.

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.

葮薆情 2024-09-14 21:27:06

添加一个示例,说明如何使用 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);
    }
}

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.

And with the PowerMockRunner the @Mock services are not wired on the @TestSubject service to test.

Let say we have a service we want to test, 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 :

import org.springframework.stereotype.Service;

@Service
public class ServiceTwo {

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

And which calls a final class static method, ServiceUtils :

public final class ServiceUtils {

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

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


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

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 :

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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文