Cannot invoke "PacienteService.findById(java.lang.Integer)" because "this.service" is null - java

I'm trying test a RestAPI in Java, but I can't mock my Service class
When start test, it gives me an error: java.lang.NullPointerException: Cannot invoke "com.tcc.tccbackend.services.PacienteService.findById(java.lang.Integer)" because "this.service" is null.
Code:
#WebMvcTest(PacienteController.class)
public class PacienteTest extends BaseTest {
#Mock
private PacienteService service;
#Autowired
private MockMvc mockMvc;
#BeforeEach
public void setup() {
RestAssuredMockMvc.mockMvc(mockMvc);
}
#Test
#DisplayName("Retorna sucesso quando busca um paciente ")
public void t4() {
Mockito.when(service.findById(9999))
.thenReturn(new Paciente(9999, "Gilberson", "gilber#gmail.com", "68211836104", "(67) 99625-5371", new Date(), List.of()));
RestAssuredMockMvc
.given()
.header("Authorization", getJWT())
.accept(ContentType.JSON)
.when()
.get("/pacientes/9999")
.then().statusCode(200);
}
BaseTest.class:
public class BaseTest {
public BaseTest(){
baseURI = "http://localhost";
port = 8080;
basePath = "/api";
}
public static String getJWT() {
return given()
.body("{\n" + "\t\"email\": \"paula#gmail.com\",\n" + "\t\"senha\": \"senha\"\n" + "}")
.contentType(ContentType.JSON)
.when()
.post("/user/login")
.then()
.extract()
.path("token");
}
}
Versions:
Java 17
RestAssured 5.3.0
SpringBoot 2.7.0
SpringBoot Starter Test 2.7.0
Junit 4.13.2

Your mixing up unit test and integration test config.
Annotations for unit tests look like this:
#ExtendWith(MockitoExtension.class)
class MyTest {
#Mock
private ServiceA myMock;
#Spy
private ServiceB mySpy;
#InjectMocks
private ServiceC myClassUnderTest;
#Test
void receive() {
// test logic
}
}
Annotations for integration tests look like this:
#ActiveProfiles("test")
#SpringBootTest
class MyTest {
#MockBean
private ServiceA myMock;
#SpyBean
private ServiceB mySpy;
#Autowired
private ServiceC myClassUnderTest;
#Test
void receive() {
// test logic
}
}
I don't know about your test config because you didn't post it here, but I suppose you should use #MockBean instead of #Mock for PacienteService service.

Related

Junit test method calling actual service method

Controller
#PostMapping("/event/confirmation")
public Mono<CallbackResponse> eventConfirmation(#RequestParam("eventId") String eventId,
#RequestBody ExecutionSummary execSummary, #RequestHeader("customerCode") String customerCode)
throws ResourceNotFoundException {
return eventService
.updateEvent(eventId, execSummary, serviceAuthClient.getDefaultJwtTokenObserver().getJwtAccessToken())
.flatMap(event -> {
return Mono.just(new CallbackResponse(true));
});
}
Test Class
#RunWith(SpringRunner.class)
#WebAppConfiguration
#AutoConfigureMockMvc
#SpringBootTest(properties = "spring.main.banner-mode=off")
public class EventStreamControllerTest {
#Mock
private ServiceAuthClient serviceAuthClient;
#Mock
private EventService eventService;
#InjectMocks
private EventStreamController eventStreamController;
#Before
public void setUp() {
Mockito.reset(eventService);
mvc = MockMvcBuilders.standaloneSetup(eventStreamController)
.setControllerAdvice(new ControllerExceptionHandler()).build();
}
#Test
public void testEventConformation() throws Exception {
ExecutionSummary executionSummary = new ExecutionSummary();
executionSummary.setErrorMessage("Test");
Mono<Event> event = Mono.just(new Event());
Mockito.when(eventService.updateEvent(Mockito.anyString(),
Mockito.any(), Mockito.anyString()))
.thenReturn(event);
RequestBuilder requestBuilder =
MockMvcRequestBuilders.post("/event/confirmation")
.contentType(MediaType.APPLICATION_JSON).header("customerCode", "456")
.param("eventId", "123")
.content(objectMapper.writeValueAsString(executionSummary));
MvcResult result = mvc.perform(requestBuilder).andReturn();
assertEquals(HttpStatus.OK.value(),result.getResponse().getStatus());
}
}
When i run the test it's actually calling original service it's not using mock service.
Can someone help me how to write a test for above controller method.
When i print the mock service invocations it's printing below output.
[Mockito] Unused stubbings of: eventService
1. eventService.updateEvent("", null, "");
- stubbed -> at com.endpoint.rest.controller.EventStreamControllerTest.testEventConformation(EventStreamControllerTest.java:158)
In you test class, you should define your eventService as a MockBean. Then it will be a mock service.
#MockBean
private EventService eventService;

spring boot integration testing mock method returns null

I wrote simple spring boot application with Controller, Service and Business classes, but while writing integration test the mock method of Service is returning null
MockMainController
#RestController
public class MockMainController {
#Autowired
private MockBusiness mockBusiness;
#GetMapping("request")
public MockOutput mockRequest() {
return mockBusiness.businessLogic(new MockInput());
}
}
MockBusiness
#Service
public class MockBusiness {
#Autowired
private MockService mockService;
public MockOutput businessLogic(MockInput input) {
return mockService.serviceLogic(input);
}
}
MockService
#Service
public class MockService {
#Autowired
private MockUtil mockUtil;
public MockOutput serviceLogic(MockInput input) {
mockUtil.exchange(UriComponentsBuilder.fromUriString(" "), HttpMethod.GET, HttpEntity.EMPTY,
new ParameterizedTypeReference<MockOutput>() {
});
return new MockOutput();
}
}
I'm trying to mock the MockService bean in application context using #MockBean
MockControllerTest
#SpringBootTest
#ActiveProfiles("test")
#Profile("test")
#RunWith(SpringJUnit4ClassRunner.class)
public class MockControllerTest {
#Autowired
private MockMainController mockMainController;
#MockBean
private MockService mockService;
#Test
public void controllerTest() {
MockOutput output = mockMainController.mockRequest();
given(this.mockService.serviceLogic(ArgumentMatchers.any(MockInput.class)))
.willReturn(new MockOutput("hello", "success"));
System.out.println(output); //null
}
}
In the test method I created mock service bean using #MockBean I'm not having any error here but System.out.println(output); prints null
You are getting null because of wrong statements order in your test method. You first call controller method and you get what's inside default #MockBean which is in this case null. Swap statement:
MockOutput output = mockMainController.mockRequest();
with
given(this.mockService.serviceLogic(ArgumentMatchers.any(MockInput.class)))
.willReturn(new MockOutput("hello", "success"));
and you will get expected result.

Spring Testing - WebTestClient Could not autowire. No beans of 'WebTestClient' type found

I want to use WebTestClient in my tests. works like this:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#AutoConfigureWebTestClient
public class ControllerTest {
#Autowired
private WebTestClient webTestClient;
#Test
public void webtestClient () {
assertNotNull(webTestClient);
}
}
But now I want to inject WebTestClient into a helper class:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#AutoConfigureWebTestClient
public class ControllerTest {
#Autowired
private Helper helper;
#Test
public void webtestClient () {
helper.check();
}
}
#Component
public class Helper {
#Autowired
private WebTestClient webTestClient;
public void check() {
assertNotNull(webTestClient);
}
}
Works, too. But Intellij is showing an error:
Could not autowire. No beans of 'WebTestClient' type found. more...
(Strg+F1)
New info: The test runs fine in Intellij, but not when running with maven.
Here is a test project with the problem:
https://github.com/kicktipp/demo
How can I use WebTestClient on my Helper class?
For what it's worth - I was able to fix this by simply specifying the AutoConfigureWebTestClient annotation explicitly:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#AutoConfigureWebTestClient
public class MyTestClass {
}
You have to build webTestClient before use it in tests
Use below, it will work
#Autowired
ApplicationContext context;
#Autowired
WebTestClient webTestClient;
#Before
public void setup() throws Exception {
this.webTestClient = WebTestClient.bindToApplicationContext(this.context).build();
}

Which type of Test is usefull for Jenkins Continous Integration (Spring Boot App)

My boss asked me to build some test on our Spring Boot application.
I'm asking myself which type of test should I implement, considering that the goal is to push the app on Jenkins that supports auto Testing.
Code based Test
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class ConfigTagControllerTestReal {
#Autowired
MockMvc mockMvc;
#Test
public void shouldReturnTheTagName() throws Exception{
this.mockMvc.perform(get("/configtag/librerie"))
.andDo(print())
.andExpect(status().isOk());
}
Completely Mock Test
#RunWith(SpringRunner.class)
#WebMvcTest(value = ConfigTagController.class , secure = false)
public class ConfigTagControllerTestMocked {
#Autowired
private MockMvc mockMvc;
#MockBean
private ConfigTagService service;
#Test
public void shouldFindTheTagName() throws Exception{
Collection<String> mockPaths= new ArrayList<>();
ConfigTagEntity mockTag = new ConfigTagEntity("culo",mockPaths);
Mockito.when(service.getByName(Mockito.anyString())).thenReturn(mockTag);
RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/configtag/culo")
.accept(MediaType.APPLICATION_JSON);
MvcResult result = mockMvc.perform(requestBuilder).andReturn();
}
I'm very new in testing and i need to understand the working method

With Spring, #InjectMock annotated test target doesn't use mocks

I'm trying to unit test a Spring 4.0.0 MVC application.
My controller is defined as follow:
#Controller
#RequestMapping("/test")
public class TestCtrl {
#Autowired
private TestService testService;
#Autowired
private TestRessourceAssembler testRessourceAssembler;
#Autowired
private ResponseComposer responseComposer;
#RequestMapping(value = "", method = RequestMethod.GET,produces = "application/json")
public HttpEntity showAll(Pageable pageable) {
Page<Test> patr = testService.getAll(pageable);
return responseComposer.composePage(patr,testRessourceAssembler);
}
#RequestMapping(value = "/{name}", method = RequestMethod.GET)
public HttpEntity<TestRessource> show(#PathVariable String name) {
Test test = testService.getOne(name);
if(test == null){
return new ResponseEntity("Erreur !",HttpStatus.NOT_FOUND);
}
return responseComposer.compose(test,testRessourceAssembler);
}
}
My controller unit test is as follow:
#RunWith(SpringJUnit4ClassRunner.class)
#ActiveProfiles("test")
#WebAppConfiguration
#ContextConfiguration(classes = {ApplicationConfig.class, TestMongoConfig.class, RestConfig.class, WebMvcConfig.class})
public class TestCtrlTests{
#InjectMocks
TestCtrl testCtrl;
#Mock
TestService testService;
#Autowired
protected WebApplicationContext wac;
protected MockMvc mockMvc;
#Before
public void setup(){
MockitoAnnotations.initMocks(this);
when(testService.getOne("jexiste")).thenReturn(new com.thalesgroup.ito.c2s.mc.portail.test.domain.Test("jexiste",1990));
when(testService.getOne("plaf")).thenReturn(null);
this.mockMvc = webAppContextSetup(this.wac).build();
}
#Test
public void simpleGetAnswer() throws Exception{
assertNotNull(mockMvc);
mockMvc.perform(get("/test")).andExpect(status().isOk());
mockMvc.perform(get("/test/jexiste")).andExpect(status().isOk());
mockMvc.perform(get("/test/plaf")).andExpect(status().isNotFound());
}
}
When I'm running the test, the "normal" TestService bean is injected and used (I can see the trace in the log), not the mock.
So I read some things on the internet and replaced
this.mockMvc = webAppContextSetup(this.wac).build();
with
this.mockMvc = standaloneSetup(TestCtrl.class).build();
But, and I knew it would happen, I've no more Spring context when doing this, so my PageableArgumentResolver and my other beans (testRessourceAssembler, responseComposer) aren't injected anymore... So they are Null and happen a NullPointerException.
My question is:
1) I'm I designing something wrong ?
2) If not, how can I inject a mock in my controller while keeping other beans from the context ?
Thanks to you !
I'm looked into your tests and this should work. Simply build your MockMvc on your controller with mocked beans. After this all mocks will be visible inside test.
A MockMvcBuilder that accepts #Controller registrations thus allowing full control over the instantiation and the initialization of controllers and their dependencies similar to plain unit tests, and also making it possible to test one controller at a time.
Don't use Spring Integration test! This is simple unit testing!
Fixed test
#RunWith(MockitoJUnitRunner.class)
public class TestCtrlTests{
#InjectMocks
TestCtrl testCtrl;
#Mock
TestService testService;
protected MockMvc mockMvc;
#Before
public void setup(){
when(testService.getOne("jexiste")).thenReturn(new com.thalesgroup.ito.c2s.mc.portail.test.domain.Test("jexiste",1990));
when(testService.getOne("plaf")).thenReturn(null);
this.mockMvc = standaloneSetup(testCtrl).build();
}
#Test
public void simpleGetAnswer() throws Exception{
assertNotNull(mockMvc);
mockMvc.perform(get("/test")).andExpect(status().isOk());
mockMvc.perform(get("/test/jexiste")).andExpect(status().isOk());
mockMvc.perform(get("/test/plaf")).andExpect(status().isNotFound());
}
}

Categories