Reputation: 657
I have something like this:
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;
}
}
I want to test the execute()
method in SomeClass
using JUnit. Since someMethod(String someArg1, String someArg2)
calls a REST API, I want to mock someMethod
to return some predefined response. But somehow, the real someMethod
gets called instead of returning the predefined response. How do I make it work?
Here is what I have tried using Mockito and 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);
}
}
Upvotes: 6
Views: 14670
Reputation: 59
This answer is very similar to answer posted by Andreas, the only difference being you can run this with @RunWith(SpringRunner.class) and it will avoid problems with bean instantiation and extra configuration. Avoid Powermocks and use it only when you need to mock static classes.
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);
}
}
Upvotes: 1
Reputation: 5103
Here is an example of injecting dependencies without a framework:
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);
}
}
Upvotes: 4
Reputation: 140457
You don't have to do that.
You change your method under test to NOT call new directly.
Instead you use dependency injection for example.
Yes, this could be done with Powermock, but please believe me: doing so is the wrong approach!
Upvotes: 1