0

Hi So I'm new to Junit and Mockito, so please bare with some misconception/mistakes that Ive made. I have a springbott service that I wanted to test and I want to mock a method call that is being made in one of the methods that I am testing but It will not work for some reason. I used both when(xxx.method(anyArgs)).return(someData) as well as doReturn(someData).when(xxx).method(anyArgs); But I still get the same type of error: InvalidUseOfMatchersException. I mock the service layer but I can not figure out what causes the issue.

The Exact Stack Trace:

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Misplaced or misused argument matcher detected here:

-> at service.EventServiceTestUnit.validatePostDataTest(EventServiceTestUnit.java:61)

You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
    when(mock.get(anyInt())).thenReturn(null);
    doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());
    verify(mock).someMethod(contains("foo"))

This message may appear after an NullPointerException if the last matcher is returning an object 
like any() but the stubbed method signature expect a primitive argument, in this case,
use primitive alternatives.
    when(mock.get(any())); // bad use, will raise NPE
    when(mock.get(anyInt())); // correct usage use

Also, this error might show up because you use argument matchers with methods that cannot be mocked.
Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().
Mocking methods declared on non-public parent classes is not supported.


    at service.EventServiceTestUnit.validatePostDataTest(EventServiceTestUnit.java:61)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:79)
    at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:85)
    at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
    at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

My Service Layer Code:

// imports here

@Service
@AllArgsConstructor
public class EventServiceImpl implements EventService {

    private EventModelRepo eventModelRepo;

    static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();

    // methods that dont matter


    public int createAPost(EventDetails eventDetails) {
        //Some where here the isOwner(STRING) is called
    }

    public static void getRequest(String reqUrl) throws IOException {
        GenericUrl url = new GenericUrl(reqUrl);
        HttpRequest request = HTTP_TRANSPORT.createRequestFactory().buildGetRequest(url);
        HttpResponse response = request.execute();


        InputStream is = response.getContent();
        int ch;
        while ((ch = is.read()) != -1) {
            System.out.print((char) ch);
        }
        response.disconnect();
    }

    public boolean isOwner(String Owner) {
        try {
            getRequest("http://localhost:9024/login/isAuth?Username=" + Owner);
        } catch (HttpResponseException e) {
            System.out.println("Error: " + e.getContent());
            return false;
        } catch (IOException e) {
            System.out.println("Could Not Connect To Site/Make Said Request. \nAre You In Testing? \nIf So This Is Ok.");
        }
        return true;
    }
}

And here is my Junit:

//imports

@RunWith(MockitoJUnitRunner.class)
public class EventServiceTestUnit {

    @Mock
    private EventModelRepo eventModelRepo;

    @InjectMocks
    private EventServiceImpl eventServiceImpl ;

    @Test
    public void validatePostDataTest() {
        // mocking the HTTP Call in isOwner()
        HttpTransport transport = new MockHttpTransport();
        HttpRequest request = null;
        try {
            request = transport.createRequestFactory().buildGetRequest(HttpTesting.SIMPLE_GENERIC_URL);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            HttpResponse response = request.execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        EventDetails eventDetails = new EventDetails("username1", "resturant", "idk", "location.", ".com",
                "no", "no p", "spring", "fair", "tes");

        //If Owner Isn't Validate As Owner/Signed In
        when(eventServiceImpl.isOwner(anyString())).thenReturn(false);
        //doReturn(false).when(eventServiceImpl).isOwner(anyString());

        eventDetails = new EventDetails("username", "resturant", "idk", "location.", ".com",
                "no", "no p", "fall", "fair", "tes");
        result = eventServiceImpl.validatePostData(eventDetails);
        assertEquals(10, result);

    }
}
Bhagyesh
  • 700
  • 10
  • 31
  • The reason your are getting the exception is that `eventServiceImpl` is not a mock. If you can't refactor the code you might want to look at what a `spy` is doing. You might also want to add the actual method you are trying to test: `validatePostData`. – second Nov 09 '19 at 16:32
  • @second what do you mean by want to look at what a spy is doing? Also this is for the isOwner(xxx) method not validatePostData(). – Bhagyesh Nov 10 '19 at 19:41

1 Answers1

0

So turns out one of the commentors on my post was correct. You can not mock a call from a @InjectMocks. But if you want to you need to have another annotation added to it. That annotation being @Spy. This annotation should be added in the test class, above the @InjectMocks.

More can be found here



@RunWith(MockitoJUnitRunner.class)
public class EventServiceTestUnit {

    @Mock
    private EventModelRepo eventModelRepo;

    @Spy
    @InjectMocks
    private EventServiceImpl eventServiceImpl ;

    @Test
    public void validatePostDataTest() {

        when(eventServiceImpl.isOwner(anyString())).thenReturn(false);

        eventDetails = new EventDetails("username", "resturant", "idk", "location.", ".com",
                "no", "no p", "fall", "fair", "tes");

        result = eventServiceImpl.validatePostData(eventDetails);
        assertEquals(10, result);

    }
}
Bhagyesh
  • 700
  • 10
  • 31
  • Just for reference check this [answer](https://stackoverflow.com/a/38573651/11514534), about why this isn't the best idea. – second Nov 10 '19 at 20:13