0

I'm new to MockMVC and junit stuffs so need a help ,so the situation is I need to mock a method while mocking the outer method which contains the method. For example method calculator(int a , int b) , i mock this method with two mock values, and within this method there is another method which does some other validations (lets say some external validations) .

I'm able to mock the main method calculator till the point where this external method is being called, i used to "Given().willReturn()" to mock the main method (calculator), and another "Given().willReturn()" statement to mock the containing method(validations one), but that gives me nullPointer exception. So I need something that could help me with this, so that the mocking can be done in an orderly fashion.

     public GuestRegistrationResponse registerGuest(SomeObject guestRegistrationRequest) throws Exception {

    SomeObject guestRegistrationResponse = new SomeObject();
    Folio folio = new Folio();

    folio.setForename(guestRegistrationRequest.getForename());
    folio.setEmail1(guestRegistrationRequest.getEmail());
    folio.setCity(guestRegistrationRequest.getCity());


    Result result = null;
    result = (Result) sampleAPICall.executeExternalAPI(result,new Class[] { SomeObject.class, User.class, Another.class, Folio.class, FolioList.class },
            Result.class);
    if (result != null && result.getFolioList() != null ) {
        guestRegistrationResponse.setFolioid(result.getFolioList().getFolio().getFolioId());

    } else {
        throw new ExternalException(result.getResult());
    }
    return guestRegistrationResponse;
}

Test method

    @RunWith(SpringRunner.class)
 @WebMvcTest(value = ServiceImpl.class, secure = true)
 public class TestServiceImpl {

@Autowired
MockMvc mockmvc;

@InjectMocks
ServiceImpl serviceImpl;

@Before
public void setUp() {
    // We would need this line if we would not use MockitoJUnitRunner
    MockitoAnnotations.initMocks(this);
    // Initializes the JacksonTester
    JacksonTester.initFields(this, new ObjectMapper());
}

@Test
public void testRegisterGuest() throws Exception {

        SomeObject mockInput = new SomeObject();

        mockInput.setCity("CITY");
            mockInput.setEmail("test@test.com");
    mockInput.setForename("FORENAME");
    /* other datat is also collected*/
    ExpectedResponse mockOutput = new ExpectedResponse();
    mockOutput.setResult(true);

    Result Result = new Result();
    Result.setMessage("success");
    Result.setStatus(true);
    processTestThatMethod(mockInput, mockOutput,  Result);
}

private void processTestThatMethod(SomeObject mockInput, ExpectedResponse mockOutput,
         ,Result result) throws Exception {
    System.out.println("Inside processTestThatMethod");
     given(serviceImpl.registerGuest(mockInput)).willReturn(mockOutput);
         // what to do below ..
             given(sampleAPICall.executeExternalAPI(any(Result.class),any(new Class[]{SomeObject.class, User.class, Another.class, Folio.class, FolioList.class}),any(Result.class))).willReturn(result);

}
}

Have edited the code @Sachin rai

Akhil KC
  • 76
  • 1
  • 8

1 Answers1

1
@Mock
    private class object;
    @Test
     public void testCalculator() {

      given(object.calculator(2,3)).willreturn(1);
      // remove the following line as when validate method will be called it will itself return true assuming it has simple check for positive value a and not calling any other method inside it
      given(class.validate(2)).willReturn(true); 
      //asserts here //
      }
corroborator
  • 321
  • 2
  • 11
  • hey , I tried this approach but the thing is while the first "given" statement gets executed it covers up the "calculator()" method right before " if(big.getResult()!=true) { " and it gives Nullpointer exception because the variable big is actually null !! So in a way my second "given" statement doesn't get a chance to get involved. – Akhil KC May 07 '19 at 11:36
  • can u show your `validate(a)` method ? if your `validate` method is returning an instance of `big` setting its `Result` value as `true` or `false ` then `big.getResult()` will not throw Null pointer exception. – corroborator May 07 '19 at 12:55
  • Hey sachin , the validate(a) method returns an object of "Result" which has 'result' and 'status' as getters/setters within it. – Akhil KC May 07 '19 at 15:03
  • have edited the code , if you find anything missing , please expect it to be present in the code, as the code is really lengthy and have cut short it to make some sense/logic .@sachin – Akhil KC May 08 '19 at 14:13
  • NB: the second given doesn't get a chance to get executed as the first invokes the method and gets stuck at the if condition in the Service. – Akhil KC May 08 '19 at 14:14
  • @david, the code is likely to give you Null Pointer Exception in else part since result will be null at this line: `if (result != null && result.getFolioList() != null ) { guestRegistrationResponse.setFolioid(result.getFolioList().getFolio().getFolioId()); } else { throw new ExternalException(result.getResult()); //NPE here, since result is null above }` – corroborator May 09 '19 at 04:53
  • exactly @sachin , so what am i supposed to do , to mock that particular code in my first given statement ?? – Akhil KC May 09 '19 at 08:46
  • `if(result!=null) { if (result.getFolioList() != null) { guestRegistrationResponse.setFolioid(result.getFolioList().getFolio().getFolioId()); } else if (result.getResult() != null) { throw new ExternalException(result.getResult()); } }else { throw new ExternalException("ANY CUSTOM EXCEPTION MESSAGE"); }` – corroborator May 09 '19 at 09:04
  • `processTestThatMethod` name must be `processTestRegisterGuest` as I guess same method is being called here. shouldn't be ? correct me. – corroborator May 09 '19 at 09:13
  • Yes both are the same @sachin : ) – Akhil KC May 09 '19 at 10:34
  • also you need to mock `sampleAPICall` instance like `@Mock SampleAPICall sampleAPICall;` near to where `@InjectMocks` is declared. pls start app in debug mode and verify line by line whether still any instance is null. let me know if you still face any prob. – corroborator May 09 '19 at 10:54
  • hey @sachin I have mocked `sampleAPICall` instance like `@Mock SampleAPICall sampleAPICall;` defined in my actual code , and debug is also done , so the thing is right before `result = (Result) sampleAPICall.executeExternalAPI(result,new Class[] { SomeObject.class, User.class, Another.class, Folio.class, FolioList.class }, Result.class);` this i have initialised the object as `Result result = null;` . but I have no option to make change the code ,I need to manage it within the Mock class. – Akhil KC May 09 '19 at 11:42
  • setting null is not a good idea anyway. you can safely set this line as `Result Result = new Result();` in `registerGuest` method instead of null. On the other hand in your `testRegisterGuest` method you can remove this same line from there and instead mock it in the same way like done for `SampleAPICall` i e. `@Mock Result result;` – corroborator May 09 '19 at 12:24
  • Even if I set the line as `Result Result = new Result();` in `registerGuest` method instead of null , It wont help me , Because `result != null && result.getFolioList() != null` the second condition should also be satisfied. – Akhil KC May 14 '19 at 10:29
  • `@Mock private Result result; @Mock FolioList folioList; @Mock Folio folio; @Before public void setUp() { //othercode ... . folio.setId(1); folioList.setFolio(folio); } @Test public void testRegisterGuest() throws Exception { //other code result.setMessage("success"); result.setStatus(true); result.setFolioList(folioList); processTestThatMethod(mockInput, mockOutput, result); ` – corroborator May 14 '19 at 12:15
  • remove `result != null` condition from `if (result != null && result.getFolioList() != null )` now when `sampleAPICall.executeExternalAPI` is called it will retun your mocked and earlier set `result` instance so that when `result.getFolioList().getFolio().getFolioId()` is called it will return 1 – corroborator May 14 '19 at 12:15
  • I'm afraid , I cant do that mate , that `result != null` is there for a reason. And if you remember the 2nd `given` statement doesn't get executed. @sachin , I am getting the error on the first Statement itself..!!! – Akhil KC May 14 '19 at 12:25
  • ok got it then leave `Result result = null;` it doesnt matter since you have dictated that `sampleAPICall.executeExternalAPI(any(Result.class),any(new Class[]{SomeObject.class, User.class, Another.class, Folio.class, FolioList.class}),any(Result.class))).willReturn(result);` your null result will be replaced by your mocked instance. but atleast you should at least set `result.setResult(someResultInstance)` so that when `result.getResult()` is called it does not throw Null Pointer Exception. – corroborator May 14 '19 at 12:45
  • pls run your code on debug mode and find the line where any method is being called on a null object; – corroborator May 14 '19 at 12:58