2

I have a piece of Java code that I need to unit-test with PowerMockito:

public class MyClass {

  public Response someMethod() {

    Response response = Wrapper.wrap( () -> {
      return OtherClass.doSomething();
    });

    // .... do something else ....

    return Response;
  }

}

It doesn't actually matter what the wrapper does, but for the sake of simplicity this is it:

public class Wrapper {

  public Response wrap(Callable<Response> callable) {
    // ...check something...
    return callable.call();
  }

}

In the unit test, I want to mock the call to OtherClass.doSomething() and verify it is called, but I don't want the wrapper to actually perform any actions beyond the lambda expression. How do I accomplish this?

Yuval
  • 7,987
  • 12
  • 40
  • 54
  • reminds me of my answer here https://stackoverflow.com/questions/48308609/how-can-i-verify-a-method-is-run-in-a-mocked-classs-callback/48325057#48325057 – Jacob Botuck Apr 13 '18 at 17:00

2 Answers2

0

I am not sure, but I believe you just want to mock a static method. You can follow the example from first answer: PowerMockito mock single static method and return object

For veryfying a call you can use verifyStatic method from PowerMockito https://automationrhapsody.com/verify-static-method-called-powermock/

staszko032
  • 802
  • 6
  • 16
  • I know how to mock a static call... My concern here is with capturing the lambda expression. – Yuval Apr 09 '18 at 16:00
  • The lambda expression seems to do a static call, so in the end, to check your lambda, you will have to verify that your static call to `OtherClass.doSomething()` was done. – Florian Schaetz Apr 10 '18 at 06:57
0

As @staszko032 already pointed out, your problem is not the lambda, your problem are static method calls - which are often a pain in the... behind to test. As long as Wrapper.wrap (or, more likely, Otherclass.doSomething()) is a static call, you need complicated tools like PowerMockito. You cannot expect throwing static calls around and still get well testable code - that's not how it works, sorry. Personally, I tend to say that PowerMockito is a tool used to solve problems you only have because the code is bad. Refactoring (if possible) should always be preferred to PowerMockito or similar tools.

So, personally, I would refactor it, for example by making the Wrapper class not static but instead inject an instance into it. This way, you can inject a mock in your test.

Of course, this will not actually solve your problem, since then you can verify that wrap(...) was called and you can even get your hands on the lambda which was given as a parameter, but the lambda will again call Otherclass.doSomething(), which is again hard to test. So doing the refactoring here might be the better idea: Inject an instance of Otherclass instead of that static call, use a mock in your test and bingo, you can verify that doSomething was called:

public class MyClass {

  private OtherClass otherClassInstance; // setter/constructor/autowire/whatever     

  public Response someMethod() {

    Response response = Wrapper.wrap( () -> {
      return otherClassInstance.doSomething(); // now that's testable
    });

    // .... do something else ....

    return Response;
  }

}
Florian Schaetz
  • 10,454
  • 5
  • 32
  • 58
  • My problem is NOT the static method, it IS the lambda expression. This isn't my first unit-test, nor the first time I've tested a static method. For future reference, this is how you mock a static call: `mockStatic(OtherClass.class); when(OtherClass.doSomething()).thenReturn(mockResponse);` – Yuval Apr 11 '18 at 07:17
  • Again, PowerMock, etc. are tools you only need because the code is bad. The solution for bad code is refactoring and not throwing more bad code at it. – Florian Schaetz Apr 11 '18 at 07:19
  • I'm working with a lot of legacy code. It would literally be easier to rewrite the whole damn codebase than to start refactoring... :-( – Yuval Apr 11 '18 at 07:20
  • 1
    Testing a lambda expression is not harder than testing other code. In your case, simply realize what it actually is: An anonymous instance of the interface Callable. Of course, anonymous instances are not easy to test, but the same principles apply here. If refactoring is out of the question, you can only test the results, which means static mocking, probably. – Florian Schaetz Apr 11 '18 at 14:58