0

I have a class definition as follows:

public class MyClass {

    public performExecution(ParamsClass paramsClassObject);
}

public ParamsClass {
    private String field1;
    private String field2;
}

Now, I want to mock the method performExecution based on the field1, but there is no direct way to do it even with the ArgumentMatchers.

Suppose I mocked the class:

MyClass myClass = mock(MyClass.class)

Now, I want to perform something like this: when the Params object passed in myClass.performExecution() has the field1 value as "1", then give a certain response, otherwise some other response.

Is that a way to do that ?

  • 1
    I don't think you understand the concept of mocking just yet. Mocking is used to e.g. "fake" a database, by intercepting the e.g. `repo.findById()` method and just return a pre-made object. It's not used to test an actual class. – Z-100 Feb 06 '23 at 10:58
  • It's not always a database, it's about mocking a class which is already tested, and whose functionality is used in another class, and hence its functionality is being mocked. – GlidingSwords997 Feb 06 '23 at 11:47
  • The database was an exapmle (e.g. ->exempli gratia -> for example). Where exactly are you injecting your mock? Are you trying to mock the method `performExecution()`? – Z-100 Feb 06 '23 at 12:07
  • Yes, I am trying to mock this method performExecution() which is a method contained inside the class MyClass. Now, I have created a mocked instance of this class, but I am not able to return a conditional response based on the field of the parameter passed to this method. – GlidingSwords997 Feb 06 '23 at 12:09
  • How does your mock work? Does it look something like this: `when(myClass.performExecution(any(ParamsClass.class)).thenReturn(...)`? Because if so, you can just create two instances of `ParamsClass` and alter the `any(...)` to match either of the two instances. This also means, you would need to write the whole `when(...).thenReturn(...)` twice – Z-100 Feb 06 '23 at 12:12
  • This still doesn't seem like a good case for mocking, this seems like a use case for just creating a custom implementation of MyClass. – Louis Wasserman Feb 06 '23 at 16:19

1 Answers1

0

There are a couple of options:

Option 1: Custom argument matcher

See for example Custom Argument Matcher by baeldung

Option 2: when / thenAnswer

@Test
void testThenAnswer() {
    MyClass myCollaborator = Mockito.mock(MyClass.class);
    when(myCollaborator.performExecution(any(ParamsClass.class)))
            .thenAnswer((invocationOnMock -> {
        ParamsClass params = invocationOnMock.getArgument(0);
        return "f1".equals(params.getField1())
                ? "V1"
                : "V2";
    }));

    var result = myCollaborator.performExecution(new ParamsClass("f1", "f2"));
    Assertions.assertThat(result).isEqualTo("V1");
}

Option 3: argThat Matcher

@Test
void testArgThat() {
    MyClass myCollaborator = Mockito.mock(MyClass.class);
    when(myCollaborator.performExecution(Mockito.argThat(p -> p != null && "f1".equals(p.getField1())))).thenReturn("V1");
    when(myCollaborator.performExecution(Mockito.argThat(p -> p != null && !"f1".equals(p.getField1())))).thenReturn("V2");

    var result = myCollaborator.performExecution(new ParamsClass("f1", "f2"));
    Assertions.assertThat(result).isEqualTo("V1");
}

Note null checks in argThat matchers

Lesiak
  • 22,088
  • 2
  • 41
  • 65