spring boot restcontroller test returns null - spring-boot

I'm testing the "find" method of the controler that returns a "findById" but the return is always null.
My project is structured as follows:
I have a LegalPerson entity
A repository that extends a JpaRepository
And a service that "uses" the repository.
#SpringBootTest
#AutoConfigureMockMvc
#ExtendWith(SpringExtension.class)
class LegalPersonResourceTest {
#MockBean
private LegalPersonService service;
#Autowired
private MockMvc mvc;
#Test
void find() {
var localDate = LocalDate.of(1955, 10, 25);
List<Long> subsidiaries = new ArrayList<>() {{
add(10L);
add(20L);
}};
List<Long> phones = new ArrayList<>() {{
add(50L);
add(60L);
}};
var mockLP = LegalPerson.builder()
.id(1L)
.active(true)
.companyId(1L)
.tradeName("Test Company Trade Name")
.companyName("Test Company Company Name")
.email("test#com")
.cnpj("testCNPJ")
.stateRegistration("test state Registration")
.municipalRegistration("test Municipal Resgistration")
.openingDate(localDate)
.address(1L)
.companyType(CompanyEnum.HEADOFFICE)
.subsidiaries(subsidiaries)
.phones(phones)
.build();
Mockito.doReturn(mockLP).when(service).find(1L);
}
}
I wonder what I'm forgetting, or writing wrong.
EDITED 01 :
Mockito.when(this.service.find(ArgumentMatchers.eq(1L))).thenReturn(mockLP);
mvc.perform(MockMvcRequestBuilders.get("/api/clients/lp/{id}", 1L))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().contentType("application/json;charset=UTF-8"))
.andExpect(MockMvcResultMatchers.jsonPath("$.active", Matchers.is(true)));
It works perfectly.
But if I add
.andExpect(MockMvcResultMatchers.header().string(HttpHeaders.ETAG, "\"1\""))
return null.

You only are mocking the service, but no testing anything in this code, you may want to test the controller, something like this:
import static org.mockito.BDDMockito.given;
#Test
public void shouldGetAPerson() throws Exception {
//...
given(service.find(1L)).willReturn(mockLP);
mvc.perform(MockMvcRequestBuilders.get("/person/1")
.contentType("application/json"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id", Matchers.containsString("1")));
}

Try with ArgumentMatchers
Mockito.when(this.service.find(ArgumentMatchers.eq(1L)).thenReturn(mockLP);

Related

Error when mocking a repository in unit test of a spring webflux application (using JUnit and Mockito)?

I am yet to find a solution to this.
My Test class:
#WebFluxTest(controllers = {PatronController.class})
#Import({PatronService.class}) //to satisfy PatronController dependency.
#ExtendWith({PatronParameterResolver.class})
class PatronFunctionsSpec {
private Patron patron;
private Mono<Patron> patronMono;
private final PatronService patronService = Mockito.mock(PatronService.class);
#MockBean
private PatronRepository patronRepository;
#Autowired
private WebTestClient client;
#BeforeEach
void init(Patron injectedPatron) {
patron = injectedPatron;
patronMono = Mono.just(patron);
}
//Patron Story: patron wants to create an account with us
#Nested
#DisplayName("Creating a patron.")
class CreatingPatron {
#Test
#DisplayName("PatronService.create() returns success msg in Response obj after creating patron.")
void getResponseObjFromServiceCreate() {
Flux<Patron> patronFlux = Flux.from(patronMono);
Mockito.when(patronRepository.saveAll(patronMono)).thenReturn(patronFlux);
PatronService patronService = new PatronService(patronRepository);
Mono<Response> responseStream = patronService.create(Mono.just(patron));
Mono<Response> expectedResponseStream = Mono.just(new Response("Welcome, patron. Can't show emojis yet -- sorry."));
assertEquals(expectedResponseStream, responseStream);
}
}
}
See my PatronService class with its code:
#Service
public class PatronService {
private final PatronRepository patronRepository;
public PatronService(PatronRepository patronRepository) {
this.patronRepository = patronRepository;
}
/**
*
* persists patron via PatronRepo
*/
public Mono<Response> create(Mono<Patron> patronMono) {
patronRepository.saveAll(patronMono).subscribe();
return Mono.just(new Response("Welcome, patron. Can't find the emojis yet -- sorry."));
}
}
I am testing the PatronService's create(), so need to mock and stub PatronRepository and its function respectively. But the problem is: after running the test case, I get this exception:
java.lang.NullPointerException: Cannot invoke "reactor.core.publisher.Flux.subscribe()" because "patronFlux" is null
at com.budgit.service.PatronService.create(PatronService.java:26)
How can I fix this?

Spring Boot Testing with Mockito and ExpectedException - console printing 'null' is normal?

I'm writing some test classes for my services and noticed a weird behavior that happens after test results are returned. The console prints 'null' messages and no other information about tests. The tests work fine as I've tried to fail them to ensure that is the case. Is this the expected behavior?
#RunWith(MockitoJUnitRunner.class)
public class GradeServiceTest {
#Rule
public ExpectedException thrown = ExpectedException.none();
#Mock
private GradeRepository gradeRepository;
#Mock
private AssignmentService assignmentService;
#InjectMocks
private GradeService gradeService;
private Assignment assignment;
private Grade grade;
#Before
public void init() {
assignment = new Assignment.Builder()
.withId(0L)
.withModuleId(0L)
.withName("Test assignment")
.withWeightEnabled(false)
.withWeight(0)
.build();
grade = new Grade.Builder()
.withId(0L)
.withAssignmentId(0L)
.withGradeType(GradeType.PERCENTAGE)
.withGradeValue("50%")
.build();
}
#Test
public void shouldAddGrade() throws AssignmentException, GradeException {
// GIVEN
when(assignmentService.exists(grade.getAssignmentId())).thenReturn(true);
when(gradeRepository.insert(any())).thenReturn(grade);
// WHEN
Grade addedGrade = gradeService.addGrade(grade.getAssignmentId(), grade.getType().name(), grade.getValue());
// THEN
assertThat(addedGrade).isEqualTo(grade);
}
#Test
public void shouldNotAddGradeIfAssignmentDoesNotExist() throws AssignmentException, GradeException {
// GIVEN
when(assignmentService.exists(grade.getAssignmentId())).thenReturn(false);
// EXPECT
thrown.expect(AssignmentException.class);
thrown.expectMessage(AssignmentErrorMessages.NOT_FOUND);
// THEN
gradeService.addGrade(grade.getAssignmentId(), grade.getType().name(), grade.getValue());
}
}
I don't think this is normal behavior for each test to be printing 'null' without any other information. Could someone help me understand what is wrong with the code?
Test results:
null
null
Process finished with exit code 0

Testing Spring Retry Circuit Breaker

I am using Spring Retry Circuit Breaker in one of my Spring Boot applications as:
#CircuitBreaker(include = CustomException.class, maxAttempts = 3, openTimeout = 2000L, resetTimeout = 4000L)
StudentResponse getStudentInfo(String studentId) {
StudentResponse res = studentRepository.getInfoByStudentId(studentId);
return res;
}
#Recover
StudentResponse recoverStudentInfo(CustomException ex, String studentId) {
throw new StudentApiException("In recovery...");
}
Now I'm trying to test it using Junit 5 as:
#ExtendWith(SpringExtension.class)
#SpringBootTest
#EnableRetry
public class StudentServiceTest {
#Autowired
StudentService studentService;
#MockBean
StudentRepository studentRepository;
#Test
public void testCircuitBreakGetStudentInfo(){
String id = "id";
doThrow(CustomException.class).when(studentRepository).getInfoByStudentId(id);
StudentResponse res = this.studentService.getStudentInfo(id);
verify(studentRepository, times(3)).getInfoByStudentId(id); // this is telling that there has been 1 interaction with the mock
}
}
Then I tried:
#Test
public void testCircuitBreakGetStudentInfo(){
String id = "id";
doThrow(CustomException.class).when(studentRepository).getInfoByStudentId(id);
assertThrows(StudentApiException.class,
()->{ this.studentService.getStudentInfo(id); }); // this is also telling that there has been 1 interaction with the mock instead of 3
}
Shouldn't there be 3 interactions? Or will it be one? Any explanation will be of great help. Any other tips on testing the circuit breaker is appreciated (I could hardly find any example on testing this circuit breaker). Thanks

#WebMvcTest content is null

I've already read this Q&A but it didn't solve the problem. I'm using Spring Boot 1.4.2.RELEASE and I'm attempting to speed up my tests. Up to this point, I've used #SpringBootTest and I'm testing switching some of these simpler tests to #WebMvcTest.
My controller has the following method which is responding to GET requests.
public ResponseEntity<MappingJacksonValue> fetchOne(#PathVariable Long id, #RequestParam(value = "view", defaultValue = "summary", required = false) String view) throws NotFoundException {
Brand brand = this.brandService.findById(id);
if (brand == null) {
throw new NotFoundException("Brand Not Found");
}
MappingJacksonValue mappingJacksonValue = jsonView(view, brand);
return new ResponseEntity<>(mappingJacksonValue, HttpStatus.OK);
}
My test looks like this:
#RunWith(SpringRunner.class)
#WebMvcTest(BrandController.class)
public class BrandSimpleControllerTest {
#Autowired
private MockMvc mockMvc;
#MockBean
private BrandService brandService;
#Test
public void testExample() throws Exception {
Brand brand = new Brand(1l);
brand.setName("Test Name");
brand.setDateCreated(new Date());
brand.setLastUpdated(new Date());
when(this.brandService.findById(1l)).thenReturn(brand);
this.mockMvc.perform(get("/api/brands/1").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name", is("Test Name")));
}
}
When I run this test, I get nothing back in the content. I'm not doing anything significantly different than this guide, so not sure what I'm missing.
I should note that using #SpringBootTest with the exact same controller works as expected.

Unit testing #PreAuthorized(hasRole) controller methods

I'm trying to write unit test for this controller method
#PreAuthorize("hasRole(#d.code) or hasRole('ROLE_ALL_ACCESS')")
#RequestMapping(value = "{department}/{examination}", method = RequestMethod.GET)
public String show(ModelMap model, Principal principal, Locale locale, D d) {
model.addAttribute(service.getItem(d) //THIS CAUSES NULL ON TEST
.addAttribute(new DateTime())
.addAttribute(locale);
return "show";
I tried this
#Test (expected=AccessDeniedException.class)
public void testShowAccessDenied() {
super.simulateRole("ROLE_STUDENT");
controller.show(new ModelMap(), Helper.getTestPrincipal(), Locale.getDefault(), new D());
But it causes NullPointerException on the marked line, which means test is running the method instead of throwing AccessDeniedException based on the wrong role.
My super test class is
public class AuthorizeTestBase {
private Mockery jmock = new JUnit4Mockery();
private AuthenticationManager authenticationManager= jmock.mock(AuthenticationManager.class);
#Before
public void setUp() {
jmock.checking(new Expectations() {{ ignoring(anything()); }});
}
protected void simulateRole(String role) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority(role));
PreAuthenticatedAuthenticationToken pat = new PreAuthenticatedAuthenticationToken(Helper.getTestPrincipal(), "", authorities);
SecurityContextHolder.getContext().setAuthentication(authenticationManager.authenticate(pat));
}
Helper.getTestPrincipal is
LdapPerson.Essence essence = new LdapPerson.Essence();
LdapPerson user = (LdapPerson) essence.createUserDetails();
return new PreAuthenticatedAuthenticationToken(user, "password");
I think I'm missing something on mocking authenticationManager. Help me!
The NPE is happeing when you try to call the service. Your class AuthorizeTestBase doesn't know about any spring beans service/dao etc . So it should load the spring wire configuration. The below is an example.
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration(locations = {"classpath:/applicationContext-test.xml",
"classpath:/applicationContext-ABC-test.xml",
"classpath:/applicationContext-DEF-test.xml",
"classpath:/applicationContext-serviceGHI-test.xml",
"classpath:/applicationContext-securityHIJ-test.xml"
})
public class AuthorizeTestBase {
.....
}
Also please have a look into - Spring MVC Test Framework

Resources