Karle
Karle

Reputation: 888

Mockito - intercept any method invocation on a mock

Is it possible to intercept all method invocations on a mock in a generic way?

Example

Given a vendor provided class such as:

public class VendorObject {

    public int someIntMethod() {
        // ...
    }

    public String someStringMethod() {
        // ...
    }

}

I would like to create a mock that re-directs all method calls to another class where there are matching method signatures:

public class RedirectedToObject {

    public int someIntMethod() {
        // Accepts re-direct
    }

}

The when().thenAnswer() construct in Mockito seems to fit the bill but I cannot find a way to match any method call with any args. The InvocationOnMock certainly gives me all these details anyway. Is there a generic way to do this? Something that would look like this, where the when(vo.*) is replaced with appropriate code:

VendorObject vo = mock(VendorObject.class);
when(vo.anyMethod(anyArgs)).thenAnswer(
    new Answer() {
        @Override
        public Object answer(InvocationOnMock invocation) {

            // 1. Check if method exists on RedirectToObject.
            // 2a. If it does, call the method with the args and return the result.
            // 2b. If it does not, throw an exception to fail the unit test.

        }
    }
);

Adding wrappers around the vendor classes to make mocking easy is not an option because:

  1. Too large an existing code base.
  2. Part of extremely performance critical applications.

Upvotes: 30

Views: 24687

Answers (1)

jhericks
jhericks

Reputation: 5971

I think what you want is:

VendorObject vo = mock(VendorObject.class, new Answer() {
    @Override
    public Object answer(InvocationOnMock invocation) {

        // 1. Check if method exists on RedirectToObject.
        // 2a. If it does, call the method with the args and return the
        // result.
        // 2b. If it does not, throw an exception to fail the unit test.

    }
});

Of course, if you want to use this approach frequently, no need for the Answer to be anonymous.

From the documentation: "It's quite advanced feature and typically you don't need it to write decent tests. However it can be helpful when working with legacy systems." Sounds like you.

Upvotes: 44

Related Questions