1

Here is my Controller:


@RestController
public class LoanController {
    
    @Autowired 
    private LoanService loanService;
        
    @GetMapping("/loans/{id}")
    public Loan getLoan(@PathVariable Long id) {
        return loanService.getLoan(id);
    }   
    
    @PostMapping("/loans")
    public ResponseEntity <String> addLoan(@RequestBody Loan loan) {
        System.out.println(" Test 2 >> " + loanService.isLoanProcessed(loan));
        
        if(loanService.isLoanProcessed(loan)) {
            return ResponseEntity.status(HttpStatus.CREATED).build(); //return http 201 return code
        }
        return ResponseEntity.status(HttpStatus.CONFLICT).build(); // return http 409 return code
        
    }   
}

Service :

@Service
public class LoanService {
    
    @Autowired
    private LoanRepository loanRepo;

    public boolean isLoanProcessed(Loan loan) {
        // Validate the Loan
        if(isValid(loan)) {
            
            // Get the Loan Fee
            Double loanFees = getLoanFees(loan.getLoanType().trim());
            
            // Get the total Loan Interest
            Double totLoanInterest = calcLoanTotalInterest(loan.getLoanAmt(),loan.getRate(),loan.getLoanTerm());
            
            // Get the APR
            Double apr = getAPR(totLoanInterest,loanFees,loan.getLoanAmt(),loan.getLoanTerm());
            
            // Set calculate APR to Loan model
            loan.setApr(apr);
            
            // Add the loan to db
            this.addLoan(loan);
            
            return true;
            
        } else {
            // If the Loan is not valid throw custom exception
            // Still need to be implemented
            return false;
        }
}

Here is the TestClass :

@SpringBootTest
@AutoConfigureMockMvc
public class LoanControllerIntegrationTests {
    
    @Autowired
    private MockMvc mockMvc;
    
    @MockBean
    private LoanService mockLoanService;
    private AutoCloseable closeable;
    
    @InjectMocks
    LoanController loanController;
    
    private Loan loan;
    private SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
    
    
    @BeforeEach
    public void init() throws Exception {
        closeable = MockitoAnnotations.openMocks(this);
        
        mockMvc = MockMvcBuilders.standaloneSetup(loanController).build();
        
    }

   @Test
    @DisplayName("POST /loans")
    final void addLoanIdTest() throws Exception {
        loan.setApr(Double.valueOf(5.15));
        loan.setLoanStatus("A");
        
        when(mockLoanService.isLoanProcessed(loan)).thenReturn(true);
        
        System.out.println(" Test 1 >> " + mockLoanService.isLoanProcessed(loan));  // printing true
        
        mockMvc.perform(post("/loans")
                .contentType(MediaType.APPLICATION_JSON)
                .content(convertObjToJsonString(loan)))
                .andExpect(status().isOk());
          
    }  

Here is my question : In the test, mocking happening correctly when I print on mockLoanService.isLoanProcessed(loan) value is correct which is true, But in Controller, post method modified mocking data is not picking, when I print showing as false, condition check on controller if(loanService.isLoanProcessed(loan)) not happening using mocking data. Please provide your input where I am making mistake.

2
  • What makes you think it’s not working, because the assertion fails? You are returning HTTP status created in your controller, but verifying for HTTP staus ok in the test. Commented Apr 18, 2021 at 7:56
  • I want the mocking service in the controller loanService.isLoanProcessed(loan); controller needs to evaluated true so that controller should execute the return ResponseEntity.status(HttpStatus.CREATED).build(); and return 201. Please let me know if you need more info. Commented Apr 18, 2021 at 13:39

2 Answers 2

1

It's not working because you are binding mock to particular Loan object created in LoanControllerIntegrationTests class. The object created in controller is not the same object.

Simple example: enter image description here

To solve your issue, please use any() operator:

when(mockLoanService.isLoanProcessed(any(Loan.class))).thenReturn(true);

that you can obtain from following import statement: import static org.mockito.ArgumentMatchers.any;

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, it solved my problem. Then my next question how to get the controller-generated Loan object.
I assume you want to check controller response. To access response json use jsonPath, example: .andExpect(jsonPath("$.loanValue").value(123.456f))
-1

in your before method, try adding:

MockitoAnnotations.initMocks(this);

2 Comments

init() method added closeable = MockitoAnnotations.openMocks(this); thought this is going initialize the mock.
initMocks() is deprecated in favor of openMpcks/close

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.