How to use random port for JUNIT Testcases using Spring Boot 1.4.0 + - spring

I am using spring boot 1.3.6 and my JUNIT Test cases are running fine, after upgrading to spring boot 1.4.0 and attempting to remove deprecated classes is throwing me error
My JUNITCLASS with 1.3.x
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
#IntegrationTest({"server.port=0"})
public class CustomerControllerIT {
#Value("${local.server.port}")
private int port;
private URL base;
private RestTemplate template;
#Autowired
private DataBuilder dataBuilder;
#Autowired
private CustomerRepository customerRepository;
private static final String JSON_CONTENT_TYPE = "application/json;charset=UTF-8";
#Before
public void setUp() throws Exception {
this.base = new URL("http://localhost:" + port + "/rest/customers");
template = new TestRestTemplate();
/* remove and reload test data */
customerRepository.deleteAll();
dataBuilder.createCustomers().forEach(customer -> customerRepository.save(customer));
}
#Test
public void getAllCustomers() throws Exception {
ResponseEntity<String> response = template.getForEntity(base.toString(), String.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
List<Customer> customers = convertJsonToCustomers(response.getBody());
assertThat(customers.size(), equalTo(3));
}
private List<Customer> convertJsonToCustomers(String json) throws Exception {
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(json, TypeFactory.defaultInstance().constructCollectionType(List.class, Customer.class));
}
}
MyClass with 1.4.0
Updates done
Removed deprecated TestRestTemplate with spring suggested one
Running with SpringRunner instead of SpringJUnit4ClassRunner
Replaced #SpringApplicationConfiguration(classes = Application.class) with #SpringBootTest(classes = Application.class , webEnvironment=WebEnvironment.RANDOM_PORT)
After Changes
#RunWith(SpringRunner.class)
#SpringBootTest(classes = Application.class , webEnvironment=WebEnvironment.RANDOM_PORT)
#WebAppConfiguration
public class CustomerControllerIT {
#Value("${local.server.port}")
private int port;
private URL base;
private TestRestTemplate template;
#Autowired
private DataBuilder dataBuilder;
#Autowired
private CustomerRepository customerRepository;
private static final String JSON_CONTENT_TYPE = "application/json;charset=UTF-8";
#Before
public void setUp() throws Exception {
this.base = new URL("http://localhost:" + port + "/rest/customers");
template = new TestRestTemplate();
/* remove and reload test data */
customerRepository.deleteAll();
dataBuilder.createCustomers().forEach(customer -> customerRepository.save(customer));
}
}
Now I am receiving NPE when i try to run JUNIT Testcase, How can I set the random port to make my JUNIT test case running in Spring Boot 1.4.0 +?
Update :
Here is the stacktrace of the issue
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:189)
at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:131)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.NullPointerException
at org.springframework.test.context.web.socket.MockServerContainerContextCustomizer.customizeContext(MockServerContainerContextCustomizer.java:38)
at org.springframework.boot.test.context.SpringBootContextLoader$ContextCustomizerAdapter.initialize(SpringBootContextLoader.java:270)
at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:633)
at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:347)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:111)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
... 25 more

From Spring Blog I have updated your latest sample.
#RunWith(SpringRunner.class)
#SpringBootTest(classes = Application.class, webEnvironment=WebEnvironment.RANDOM_PORT)
public class CustomerControllerIT {
#Autowired
private TestRestTemplate template;
#Autowired
private DataBuilder dataBuilder;
#Autowired
private CustomerRepository customerRepository;
private static final String JSON_CONTENT_TYPE = "application/json;charset=UTF-8";
#Before
public void setUp() throws Exception {
/* remove and reload test data */
customerRepository.deleteAll();
dataBuilder.createCustomers().forEach(customer -> customerRepository.save(customer));
}
#Test
public void getAllCustomers() throws Exception {
ResponseEntity<String> response = template.getForEntity("/rest/customers", String.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
List<Customer> customers = convertJsonToCustomers(response.getBody());
assertThat(customers.size(), equalTo(3));
}
}

for JUNIT 5 the solution that worked for me is the bellow (taken from Spring's documentation):
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.beans.factory.annotation.Value;
import static org.assertj.core.api.Assertions.assertThat;
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class HttpRequestTest {
#Value(value="${local.server.port}")
private int port;
#Autowired
private TestRestTemplate restTemplate;
#Test
public void greetingShouldReturnDefaultMessage() throws Exception {
assertThat(this.restTemplate.getForObject("http://localhost:" + port + "/",
String.class)).contains("Hello, World");
}
}
The interesting points are:
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
For the bellow there is no need for further configuration in application.properties for example. It works as is:
#Value(value="${local.server.port}")
private int port;
Then you autowire the testRestTemplate and include the baseUrl in the call to your endpoint.

Related

Usage of Config classes in integratiion testing scenario with #SpringJUnitConfig

I am trying to explore the Spring framework developing a very basic application based on one of my hobbies.
There is a null error when trying to execute a test that i am not really not understanding.
I have a Class tagged as a #Component:
package matchedbetting;
...
#Component("bet")
public class Bet {
private String team1;
private String team2;
...
public Bet(String team1, String team2, String league, double bookmaker, double exchange, double commission) {
super();
this.team1 = team1;
this.team2 = team2;
...
this.commission = commission;
}
#Autowired
public Bet() {
super();
}
}
I have a #Configuration class that imports another Configuration for aspects and scans for component in different packages:
package config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
#Configuration
#Import({AspectsConfig.class})
#ComponentScan({"matchedbetting","utils"})
public class MyTrainingConfig {
}
And in my test package i have a Config class that imports it:
package matchedbetting;
...
import config.MyTrainingConfig;
#Configuration
#Import({MyTrainingConfig.class})
public class MatchedBettingTestConfig {
#Bean MatchedBetting matchedBetting() {
return new MatchedBettingImpl();
}
}
Now i run my test and everything looks fine:
package matchedbetting;
...
import org.springframework.context.ConfigurableApplicationContext;
import utils.FieldConsistency;
public class MatchedBettingImplTests {
private ConfigurableApplicationContext context;
private Bet bet;
private FieldConsistency fieldConsistency;
private MatchedBetting matchedBetting;
#Before
public void setUp() {
context = SpringApplication.run(MatchedBettingTestConfig.class);
bet = context.getBean(Bet.class);
fieldConsistency = context.getBean(FieldConsistency.class);
matchedBetting = context.getBean(MatchedBetting.class);
}
#Test
public void test() {
setTestingBet(bet);
fieldConsistency.checkTeam(bet);
System.out.println("Rating Bet: " + matchedBetting.calculateRating(bet));
}
private void setTestingBet(Bet bet) {
bet.setTeam1("teamA");
...
bet.setCommission(0.01);
}
}
Now i am trying to switch to Spring testing :
package matchedbetting;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import utils.FieldConsistency;
#SpringJUnitConfig(classes=MatchedBettingTestConfig.class)
public class MatchedBettingImplTests {
#Autowired
private Bet bet;
#Autowired
private MatchedBetting matchedBetting;
#Autowired
private FieldConsistency fieldConsistency;
#Test
public void test() {
setTestingBet(bet);
fieldConsistency.checkTeam(bet);
System.out.println("Rating Bet: " + matchedBetting.calculateRating(bet));
}
private void setTestingBet(Bet bet) {
bet.setTeam1("teamA");
...
bet.setCommission(0.01);
}
}
But the test comes out with the error that "bet" is null. I really don't understand what i am missing.
java.lang.NullPointerException: Cannot invoke "matchedbetting.Bet.setTeam1(String)" because "bet" is null
at matchedbetting.MatchedBettingImplTests.setTestingBet(MatchedBettingImplTests.java:35)
at matchedbetting.MatchedBettingImplTests.test(MatchedBettingImplTests.java:28)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:93)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:756)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Any thoughts?
Thank you
Trying to switch integration testing using #SpringJUnitConfig
i was running the #Test as Junit4. Just switched to org.junit.jupiter.api.Test and now running the test as JUnit5 ends like expected
package matchedbetting;
import org.junit.jupiter.api.Test; //changed this
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import utils.FieldConsistency;
#SpringJUnitConfig(classes=MatchedBettingTestConfig.class)
public class MatchedBettingImplTests {
#Autowired
private Bet bet;
#Autowired
private MatchedBetting matchedBetting;
#Autowired
private FieldConsistency fieldConsistency;
#Test //changed this
public void test() {
setTestingBet(bet);
fieldConsistency.checkTeam(bet);
System.out.println("Rating Bet: " + matchedBetting.calculateRating(bet));
}
private void setTestingBet(Bet bet) {
bet.setTeam1("teamA");
bet.setBookmaker(1.5);
bet.setExchange(2);
bet.setCommission(0.01);
}
}

How to mock spring security cookies session in spring boot unit Test?

I have added Http cookie Authentication using authentication manager to my Spring Boot REST API
I have a controller that exposes a rest service allowing authentication to /api/auth/signin resource via Spring security cookies session.
Here is the the Controller and the security configuration This exemple.
After running the application, I noticed that it is important to carry out the unit test part, so I wanted to create mocks for the authenticateUser method (resource: /signin), but unfortunately I encountered problems.
Voici la classe AuthControllerTest:
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes=Application.class)
#WebMvcTest(AuthController.class)
public class AuthControllerTest {
#MockBean
UserRepository userRepository;
#MockBean
AuthenticationManager authenticationManager;
#MockBean
private UserDetailsServiceImpl userDetailsServiceImpl;
#Autowired
private MockMvc mockMvc;
private static UserDetailsImpl dummy;
#MockBean
private JwtUtils jwtUtil;
#Autowired
WebApplicationContext webApplicationContext ;
private ResponseCookie cookies;
#BeforeEach
public void setUp() {
dummy = new UserDetailsImpl(10L,"test1","test1#mail.com","123456",new ArrayList<>());
Authentication authentication = authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();*/
cookies = jwtUtil.generateJwtCookie(dummy) ;
}
#Test
#DisplayName("POST /signin")
void authenticateUser() throws Exception
{
LoginRequest authenticationRequest = new LoginRequest("mod", "123456") ;
String jsonRequest = asJsonString(authenticationRequest);
RequestBuilder request = MockMvcRequestBuilders
.post("/api/auth/signin")
.content(jsonRequest)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.accept(MediaType.APPLICATION_JSON);
Authentication auth = Mockito.mock(Authentication.class);
Mockito.when(auth.getName()).thenReturn("authName");
auth.setAuthenticated(true);
Mockito.when(auth.isAuthenticated()).thenReturn(true);
Mockito.when(authenticationManager.authenticate(auth)).thenReturn(auth); // Failing here
Mockito.when(jwtUtil.generateJwtCookie(dummy)).thenReturn(cookies);
Mockito.when(userDetailsServiceImpl.loadUserByUsername("test1")).thenReturn(dummy);
MvcResult mvcResult = mockMvc.perform(request)
.andExpect(status().is2xxSuccessful())
.andReturn();
}
public static String asJsonString(final Object obj) {
try {
return new ObjectMapper().writeValueAsString(obj);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Here is the encountered errors after running the class AuthControllerTest:
java.lang.AssertionError: Range for response status value 403
expected: but was:<CLIENT_ERROR> Expected :SUCCESSFUL
Actual :CLIENT_ERROR
at
org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:59)
at
org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:122)
at
org.springframework.test.web.servlet.result.StatusResultMatchers.lambda$is2xxSuccessful$3(StatusResultMatchers.java:78)
at
org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:212)
at AuthControllerTest.authenticateUser(AuthControllerTest.java:102)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498) at
org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at
org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at
org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at
org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at
org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at
org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at
org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at
org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at
org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
If you willing to change your code, then do this and hopefully everything will work fine:
A. Create a package in your test main package, it should include both words test and integration
package com.<yourApplication>.test.integration;
B.This is how your test class should be like:
#AutoConfigureMockMvc
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#Import({ ObjectMapper.class, <YourController>.class })
#TestMethodOrder(OrderAnnotation.class)
class YourTestClass {
#Autowired
private MockMvc mockMvc;
#Autowired
private ObjectMapper objectMapper;
// user authentication
private static String jwt; // can use this for your next test request
#Test
#Order(1)
#DisplayName("User Authentication token")
void authenticationTest() throws JsonProcessingException, Exception {
final String link = "/api/auth/signin";
AuthenticationRequest defaultAuth = new AuthenticationRequest("admin", "admin");
System.out.println(objectMapper.writeValueAsString(defaultAuth));
// perform the request
MvcResult result = this.mockMvc
.perform(MockMvcRequestBuilders.post(link)
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(defaultAuth)))
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
String response = result.getResponse().getContentAsString();
System.out.println("from response: " + response); //
JsonNode root = objectMapper.readTree(response);
JsonNode jwtvalue = root.get("jwt");
jwt = jwtvalue.textValue();
System.out.println("jwt deserlized: " + jwt);
}
}
C. If the request returned an error, then the problem is either in your controller or the way you setup the JWT authentication.

Mock test for Login Controller throwing null pointer exception for AuthenticationManager

I have an error when I try to create a post request in my Mock test. It tells me that the authenticationManager is null(meaning it wasn't autowired).
I have a Login Controller having an autowired AuthenticationManager with three methods(login/register/userinfo) .
I tried to create a Login Controller Test with an instance of LoginController having injectedMocks but I don't know how to use it(I am not accustomed to testing).
Login Controller
#RestController
#RequestMapping("/auth")
#CrossOrigin
public class LoginController {
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
JWTTokenHelper jWTTokenHelper;
#Qualifier("myUserDetails")
#Autowired
private UserDetailsService userDetailsService;
String jwtToken;
private final UserService userService;
#Autowired
LoginController(UserService userService){
this.userService = userService;
}
#PostMapping(value = "/register",consumes = "application/json")
public ResponseEntity<?> register(#RequestBody RegistrationDTO registrationDTO) throws InvalidKeySpecException, NoSuchAlgorithmException {
return this.login(new AuthenticationDTO(registrationDTO.getEmail(), registrationDTO.getPassword()));
}
#PostMapping(value = "/login",consumes = "application/json")
public ResponseEntity<?> login(#RequestBody AuthenticationDTO authenticationDTO) throws InvalidKeySpecException, NoSuchAlgorithmException {
System.out.print("\n" + authenticationDTO.getEmail() + " " + authenticationDTO.getPassword() + "\n");
final Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
authenticationDTO.getEmail(), authenticationDTO.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
UserDetails userDetails=(UserDetails) authentication.getPrincipal();
String jwtToken=jWTTokenHelper.generateToken(userDetails.getUsername());
this.jwtToken = jwtToken;
LoginResponseDTO responseDTO = new LoginResponseDTO(jwtToken);
//try to find out if it's a customer or not
return ResponseEntity.ok(responseDTO);
}
#GetMapping("/userinfo")
#ResponseBody
public ResponseEntity<?> getUserInfo(Principal user){
User userObj = (User)userDetailsService.loadUserByUsername(user.getName());
UserDTO userInfo = new UserDTO(userObj.getId(),userObj.getName(),userObj.getEmail(),userObj.getAuthorities().toArray());
return ResponseEntity.ok(userInfo);
}
}
Login Controller Test
import com.example.demo.Controller.LoginController;
import com.example.demo.Model.DTOs.AuthenticationDTO;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
#AutoConfigureMockMvc
#RunWith(MockitoJUnitRunner.class)
public class LoginControllerTest {
#Autowired
private MockMvc mockMvc;
#InjectMocks
private LoginController loginController;
#Before
public void setUp(){
mockMvc = MockMvcBuilders.standaloneSetup(loginController).build();
}
#Test
public void testLogin() throws Exception{
AuthenticationDTO authenticationDTO = new AuthenticationDTO("ztudorita#gmail.com","Shaorma72.");
mockMvc.perform(
MockMvcRequestBuilders
.post("/auth/login")
.contentType(MediaType.APPLICATION_JSON)
.content(asJsonString(authenticationDTO))
// .accept(MediaType.APPLICATION_JSON)
)
.andReturn();
}
public static String asJsonString(final Object obj) {
try {
return new ObjectMapper().writeValueAsString(obj);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
ERROR CONSOLE
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:72)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:199)
at com.example.demo.ControllerTest.LoginControllerTest.testLogin(LoginControllerTest.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.mockito.internal.runners.DefaultInternalRunner$1$1.evaluate(DefaultInternalRunner.java:55)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:100)
at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:107)
at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:41)
at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Caused by: java.lang.NullPointerException
at com.example.demo.Controller.LoginController.login(LoginController.java:59)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at

RestController Integration Tests Junit5 Error

I am development a integration tests for a RestController
#RestController
public class MyController {
//fields
private ModelMapper mapper;
private MyService myService;
//constructor
public MyController(ModelMapper mapper, Myservice myService) {
this.mapper = mapper;
this.myService = myService;
}
#GetMapping(value = "/test", produces = "application/json")
public ResponseEntity<Page<Dto>> retrieveAll(pageNumber, pageSize)
.....
and my test classes implementation
#ExtendWith(SpringExtension.class)
#WebMvcTest(MyController.class)
class MyControllerIntegrationTest {
#Autowired
MockMvc mockMvc;
#MockBean
MyService myService;
#MockBean
ModelMapper modelMapper;
#Test
void test() throws Exception{
ObjFactory objFactory = new ObjFactory();
Mockito.when(myService.retrieveAll(1,20)).thenReturn(objFactory.createRandomList());
mockMvc.perform(MockMvcRequestBuilders.get("/test"))
.andExpect(MockMvcResultMatchers.status().isOk());
}
}
and in my Mockito is returning a array with 2 model/entity elements.
i am getting this error
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
...
at java.base/java.util.ArrayList.forEach
at java.base/java.util.ArrayList.forEach
Caused by: java.lang.NullPointerException
at com.testing.john.controller.myController.retrieveAll(MyController.java:48)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
What may be the problem?
This endpoint via http client(Postman) give me 200 and give me a Page.
I am testing some strategies but doesn't works.
Thanks

Null Pointer Exception on MockMvc.perform on #Test class

I am writing to write a unit test for my RestController (POST) and I am getting a NullPointerException on mvc.perform(...) line.
Here's my RestController :
#RestController
#EnableAutoConfiguration
public class MyController {
#Autowired
private Service1 service;
#Autowired
RestTemplate restTemplate;
#RequestMapping(value = "/logError", method = RequestMethod.POST, produces = {MediaType.APPLICATION_JSON_VALUE})
#ResponseBody
public ResponseEntity ErrorHandlor(#RequestBody JSONStructure jsonStructure) throws Exception{
service.getDocument(jsonStructure.getID(), jsonStructure.getLog());
return new ResponseEntity(HttpStatus.OK);
}
}
And here is my test class:
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = {MyController.class,
Service1.class, AppConfig.class})
#WebMvcTest(MyController.class)
public class MyControllerTest {
private MockMvc mockMvc;
#MockBean
private RestTemplate restTemplate;
MyController service = new MyController();
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(service).build();
}
#Test
public void testController() throws Exception{
ObjectMapper mapper = new ObjectMapper();
String url = "http://localhost:8080/logError";
JSONStructure structure = new JSONStructure();
structure.setNumber("num");
structure.setID("id");
structure.setLog("log");
String json = mapper.writeValueAsString(structure)
this.mockMvc.perform
(MockMvcRequestBuilders.post("http://localhost:8080/logError")
.contentType(MediaType.APPLICATION_JSON)
.content(json))
.andExpect(MockMvcResultMatchers.status().isCreated())
.andReturn();
}
}
I am getting a NPE on line containing this.mockMvc.perform(...).
Can anyone point out what might the problem be?
You will get it to work in this way (i tested it):
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
#SpringBootTest
public class TestControllerImplTest {
#Mock
private TestBO TestBO; //if for example the controller calls some autowired service
private MockMvc mockMvc;
#InjectMocks //i think this was your main problem, you missed this annotation
TestControllerImpl controller;
#BeforeEach
void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
}
#Test()
void shouldReturnAllTests() throws Exception {
TestDTO testDTO = new TestDTO();
testDTO.setId(Long.valueOf(1));
List<TestDTO> allTests = new ArrayList(Arrays.asList(testDTO));
when(testBO.getAllTests()).thenReturn(allTests);
mockMvc.perform(get("/api/test/getAllTests")).andExpect(status().isOk()).andDo(print());
}
}
When using #RunWith(SpringRunner.class), use #Autowired MockMvc mockmvc.
When using #RunWith(MockitoJunitRunner.class) or MockitoAnnotations.initMocks(this) then
use this.mockMvc = MockMvcBuilders.standaloneSetup(service).build();
Don't mix both Spring and Mockito runners.

Resources