我有这样的事情:
public interface SomeInterface {
public String someMethod(String someArg1, String someArg2);
}
public class SomeInterfaceImpl {
@Override
public String someMethod(String someArg1, String someArg2) {
String response;
// a REST API call which fetches response (need to mock this)
return response;
}
}
public class SomeClass {
public int execute() {
int returnValue;
// some code
SomeInterface someInterface = new SomeInterfaceImpl();
String response = someInterface.someMethod("some1", "some2");
// some code
return returnValue;
}
}
我想使用JUnit在execute()
中测试SomeClass
方法。由于someMethod(String someArg1, String someArg2)
调用REST API,我想模拟someMethod
以返回一些预定义的响应。但不知何故,真正的someMethod
被调用而不是返回预定义的响应。我如何使它工作?
以下是我尝试使用Mockito和PowerMockito:
@RunWith(PowerMockRunner.class)
@PrepareForTest({ SomeInterface.class, SomeInterfaceImpl.class, SomeClass.class })
public class SomeClassTest {
@Test
public void testExecute() {
String predefinedResponse = "Some predefined response";
int expectedReturnValue = 10;
SomeInterfaceImpl impl = PowerMockito.mock(SomeInterfaceImpl.class);
PowerMockito.whenNew(SomeInterfaceImpl.class).withAnyArguments().thenReturn(impl);
PowerMockito.when(impl.someMethod(Mockito.any(), Mockito.any())).thenReturn(predefinedResponse);
SomeClass someClass = new SomeClass();
int actualReturnValue = someClass.execute();
assertEquals(expectedReturnValue, actualReturnValue);
}
}
答案 0 :(得分:3)
以下是在没有框架的情况下注入依赖项的示例:
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.when;
interface SomeInterface {
String someMethod(String someArg1, String someArg2);
}
class SomeInterfaceImpl implements SomeInterface {
@Override
public String someMethod(String someArg1, String someArg2) {
String response;
response = "the answer.";// a REST API call which fetches response (need to mock this)
return response;
}
}
class SomeClass {
private final SomeInterface someInterface;
SomeClass(final SomeInterface someInterface) {
this.someInterface = someInterface;
}
public SomeClass() {
this(new SomeInterfaceImpl());
}
public int execute() {
int returnValue;
// some code
String response = someInterface.someMethod("some1", "some2");
returnValue = 42; // some code
return returnValue;
}
}
@RunWith(MockitoJUnitRunner.class)
class SomeClassTest {
private static final String SOME_PREDEFINED_RESPONSE = "Some predefined response";
@Mock
private SomeInterface someInterface;
@InjectMocks
private SomeClass underTest;
@Before
public void setup() {
when(someInterface.someMethod(anyString(), anyString())).thenReturn(SOME_PREDEFINED_RESPONSE);
}
@Test
public void testExecute() {
int expectedReturnValue = 42;
int actualReturnValue = underTest.execute();
assertEquals(expectedReturnValue, actualReturnValue);
}
}
答案 1 :(得分:1)
你不必这样做。
您将测试中的方法更改为不直接调用new。
相反,您可以使用依赖注入。
是的,这可以用Powermock完成,但请相信我:这样做是错误的方法!
答案 2 :(得分:0)
这个答案与Andreas发布的答案非常相似,唯一的区别是您可以使用@RunWith(SpringRunner.class)来运行它,它将避免bean实例化和额外配置的问题。避免使用Powermocks,仅在需要模拟静态类时才使用它。
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.when;
interface SomeInterface {
String someMethod(String someArg1, String someArg2);
}
class SomeInterfaceImpl implements SomeInterface {
@Override
public String someMethod(String someArg1, String someArg2) {
String response;
response = "the answer.";// a REST API call which fetches response (need to mock this)
return response;
}
}
class SomeClass {
private final SomeInterface someInterface;
SomeClass(final SomeInterface someInterface) {
this.someInterface = someInterface;
}
public SomeClass() {
this(new SomeInterfaceImpl());
}
public int execute() {
int returnValue;
// some code
String response = someInterface.someMethod("some1", "some2");
returnValue = 42; // some code
return returnValue;
}
}
@RunWith(MockitoJUnitRunner.class)
class SomeClassTest {
private static final String SOME_PREDEFINED_RESPONSE = "Some predefined response";
@Mock
private SomeInterface someInterface;
@InjectMocks
private SomeClass underTest;
@Before
public void setup() {
when(someInterface.someMethod(anyString(), anyString())).thenReturn(SOME_PREDEFINED_RESPONSE);
}
@Test
public void testExecute() {
int expectedReturnValue = 42;
int actualReturnValue = underTest.execute();
assertEquals(expectedReturnValue, actualReturnValue);
}
}