Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I mock an implementation class?

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);
      }
}
like image 926
user87407 Avatar asked Feb 17 '17 20:02

user87407


People also ask

How do you mock the method of the same class?

Mocking is done when you invoke methods of a class that has external communication like database calls or rest calls. Through mocking you can explicitly define the return value of methods without actually executing the steps of the method.

What is a mocked class?

A mock is a fake class that can be examined after the test is finished for its interactions with the class under test. For example, you can ask it whether a method was called or how many times it was called.

What are mock methods?

Mock is a method/object that simulates the behavior of a real method/object in controlled ways. Mock objects are used in unit testing. Often a method under a test calls other external services or methods within it. These are called dependencies. Once mocked, the dependencies behave the way we defined them.


1 Answers

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);
  }
}
like image 199
Andreas Avatar answered Sep 28 '22 09:09

Andreas