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
How do I mock static methods in a class with easymock?
提问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 PowerMockRunner
the @Mock
services are not wired on the @TestSubject
service 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);
}
}