2

I am trying to mock an external API call but with the code structure I do not know whether mockito is going to help.

I have a SimpleController:

public class SimpleController extends Anothercontroller
{
  @RequestMapping("/classA")
  {
    .......
    String response = postCall(url, .....);
   }
}

public class AnotherController
{
  public String postCall (String url, ......)
  {
    //This is the apache library to make post calls
    return WebUtil.post(......);
  }
}

So now I need to mock the postCall which is a call to the external service.

Here I can mock at 2 places:

1) postCall() in the SimpleController, howevere I dont know how to do that since it favors inheritance over composition.

2) WebUtil.post(.....) however I don't know how mockito can mock a static method.

I don't want to refactor the code structure since there is also a lot of other code depenedent on it as well.

banes
  • 123
  • 1
  • 8

3 Answers3

1

If you're allowed to modify AnotherController, you can do the following: First you wrap WebUtil inside another class like so:

public class WebUtilWrapper {
     String post(.....) {
          return WebUtil.post(.....);
     }
}

Then, add a constructor to AnotherController that takes WebUtilWrapper as a parameter. This constructor will be used in your unit test:

public class AnotherController {
     private WebUtilWrapper wrapper;

     public AnotherController() {
          //default constructor
          this(new WebUtilWrapper());             
     }

     public AnotherController(WebUtilWrapper wrapper) {
          this.wrapper = wrapper;
     }

     public String postCall (String url, ......) {
          //This is the apache library to make post calls
          return this.wrapper.post(......);
     }
}

Finally also add the parameterised constructor to your SimpleController.

 public class SimpleController extends Anothercontroller {
      public SimpleController() {
           super();
      }

      public SimpleController(WebUtilWrapper wrapper) {
           super(wrapper);
      }
      .
      .
      .

Now you can mock the WebUtilWrapper (instead of WebUtil) in your unit test. The rest of your code will work normally as a default constructor is still available.

mdewit
  • 2,016
  • 13
  • 31
1

1) postCall() in the SimpleController, howevere I dont know how to do that since it favors inheritance over composition.

This is possible with Mockito using spies. A spy is a mock of an object that uses real methods unless specified otherwise.

// spyController will use real methods expect for postCall()
SimpleController spyController = Mockito.spy(new SimpleController());
Mockito.doReturn("mockedString").when(spyController).postCall();

2) WebUtil.post(.....) however I don't know how mockito can mock a static method.

This is not possible with Mockito, but there are 2 work-arrounds:

  1. Use PowerMock, which allows static mocking.
  2. Refactor you code to not call the static method directly. This is already explained in @mdewit's answer, so I'll just let you read the details there.

Personally, I think that refactoring is the cleanest solution, because having static dependencies is evil. If for whatever reason you can't or don't want to change you production code, than Mockito.spy() is a good approach.

Community
  • 1
  • 1
noscreenname
  • 3,314
  • 22
  • 30
0

PowerMock will be a reasonable option in this case to mock the WebUtil.post(). They have an example using Spring and @Rule as the default way is to use it is with @RunWith but with Spring you are normally already using that annotation.

https://github.com/jayway/powermock/blob/master/examples/spring-mockito/src/test/java/org/powermock/examples/spring/mockito/SpringExampleTest.java

Shawn Clark
  • 3,330
  • 2
  • 18
  • 30