I got this unit test code to test my spring mvc view, its look like failing to initialize the service.
@AutoConfigureMockMvc
@ContextConfiguration(classes = { TestAppContext.class })
@WebMvcTest
@Transactional
class BillEntryControllerTest {
@Autowired
private BillEntryService billEntryService;
@Autowired
private MockMvc mockMvc;
@BeforeEach
public void setup() {
this.mockMvc = MockMvcBuilders.standaloneSetup(new BillEntryController())
.build();
}
@Test
public void checkUpdateBill() throws Exception {
billEntryService = Mockito.mock(BillEntryServiceImpl.class);
doNothing().when(billEntryService).addOrUpdateBill(any(BillEntry.class));
this.mockMvc
.perform(MockMvcRequestBuilders.post("/bill-entry/saveBillEntry").accept(MediaType.TEXT_HTML)
.param("amount", "10.0")
.param("owner", "User")
.param("property", "Prop")
.param("receiptNumber", "ABC")
.param("accountName", "AC")
.param("billerName", "BN")
.param("datePaid", "20/10/2022")
.param("dateDue", "20/10/2022"))
.andExpect(model().errorCount(0)).andExpect(status().isOk());
}
}
And getting following error
Caused by: java.lang.NullPointerException: Cannot invoke "org.de.service.BillEntryService.addOrUpdateBill(org.de.model.BillEntry)" because "this.billEntryService" is null at org.de.controller.BillEntryController.saveBillEntry(BillEntryController.java:157)
@PostMapping("/saveBillEntry")
public String saveBillEntry(Model model, @Valid @ModelAttribute("billEntry") BillEntryFormDto dto,
BindingResult theBindingResult) {
BillEntry billEntry = new BillEntry();
if (dto.getBillId()!=null && !dto.getBillId().isEmpty()) {
logger.debug("biller id " + dto.getBillId());
billEntry = billEntryService.getBillEntryById(Integer.parseInt(dto.getBillId()));
}
if (theBindingResult.hasErrors()) {
logger.error("has errors ");
getDefault(model);
return "bill-entry-form";
}
//updating the form attributes
billEntry.setAccountName(dto.getAccountName());
billEntry.setAmount(Double.parseDouble(dto.getAmount().replaceAll("[^\\d.]", "")));
billEntry.setBillerName(dto.getBillerName());
billEntry.setDateDue(FormatHelper.getDateFromString(dto.getDateDue()));
billEntry.setDatePaid(FormatHelper.getDateFromString(dto.getDatePaid()));
billEntry.setProperty(dto.getProperty());
billEntry.setReceiptNumber(dto.getReceiptNumber());
billEntry.setOwner(dto.getOwner());
logger.info("attempt to save/update bill entires " + billEntry.getBillId());
logger.debug("entry " + billEntry);
//failing at here (line 157)
billEntryService.addOrUpdateBill(billEntry);
return "redirect:"+ dto.getRedirect();
}
I try to mock the BillEntryService but that didn't help me ether. Any tips on how to fix it or what I'm doing wrong?
This is because your mocked billEntryService
is not injected into the controller under test. As a result, that field is not initialized ( null
) in the controller during the test.
To fix that, the billEntryService
must be annotated with @MockBean
instead of @Autowired
in the test. That will inject the mocked version of BillingEntryService
into the controller. And you shouldn't initialize that mocked billEntryService
using Mockito.mock(...)
afterwards. The mockMvc
shouldn't be initialized either, because you are using @WebMvcTest
that already injects a proper mockMvc
and you are autowiring it. So, the @BeforeEach
method is also to be removed.
Given the above, the relevant part of the test will look like this:
@ContextConfiguration(classes = { TestAppContext.class })
@WebMvcTest
@Transactional // doesn't seem necessary here but I haven't touched this
class BillEntryControllerTest {
@MockBean
private BillEntryService billEntryService;
@Autowired
private MockMvc mockMvc;
@Test
public void checkUpdateBill() throws Exception {
doNothing().when(billEntryService).addOrUpdateBill(any(BillEntry.class));
mockMvc.perform...
}
Also, you can find this answer quite helpful.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.