Assertion Error while testing rest controller Expected :200 Actual :404 - java

I'm trying to test my simple rest controller method to get all offers but i always get java.lang.AssertionError: Status Expected :200 Actual :404. I don't know if there is problem with mocking or finding my component. I was trying to find solution in other posts but none of them was matching to my problem. Any ideas?
My Service:
#Service
#Transactional
class OfferServiceImpl implements OfferService {
private OfferRepository offerRepository;
#Autowired
public OfferServiceImpl(OfferRepository offerRepository) {
this.offerRepository = offerRepository;
}
#Override
public List<Offer> getAll(){
return (List<Offer>) offerRepository.findAll();
}
My Controller:
#RestController
#RequestMapping("/api/offers")
class OfferRestController {
private OfferService offerService;
#Autowired
public OfferRestController(OfferService offerService) {
this.offerService = offerService;
}
#GetMapping
List<Offer> getAllOffers(){
return offerService.getAll();
}
My Test Class:
#RunWith(SpringRunner.class)
#WebMvcTest(value = OfferRestController.class)
public class OfferControllerIntegrationTest {
private Offer offer1;
private Offer offer2;
#MockBean
private OfferService offerServiceMock;
#Autowired
private WebApplicationContext webApplicationContext;
#Autowired
private MockMvc mvc;
#Before
public void setUpOffers(){
offer1 = new Offer("Java Dev",
4000,
5000,
"CEO",
"Java",
"Lorem ipsum",
"user#gmail.com",
true);
offer2 = new Offer("PHP Dev",
4000,
5000,
"CEO",
"PHP",
"Lorem ipsum",
"user#gmail.com",
true);
}
#Before
public void setUp() {
this.mvc = standaloneSetup(new OfferRestController(offerServiceMock))
.alwaysExpect(MockMvcResultMatchers.content()
.contentType("application/json;charset=UTF-8"))
.defaultRequest(get("/").accept(MediaType.APPLICATION_JSON))
.alwaysExpect(status().isOk())
.build();
this.mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.alwaysDo(print())
.build();
}
#Test
public void givenOffers_whenGetOffers_thenReturnJsonArray() throws Exception{
List<Offer> allOffers= Arrays.asList(offer1,offer2);
given(offerServiceMock.getAll()).willReturn(allOffers);
mvc.perform(get("/api/offers")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$",hasSize(2)))
.andExpect(jsonPath("$[0].name").value(offer1.getName()))
.andExpect(jsonPath("$[1].name").value(offer2.getName()))
.andDo(print());
verify(offerServiceMock,times(1)).getAll();
verifyNoMoreInteractions(offerServiceMock);
}
}
My App:
#SpringBootApplication
#EntityScan(basePackageClasses = {App.class, Jsr310JpaConverters.class})
#ComponentScan({"com"})
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
And my problem:
MockHttpServletRequest:
HTTP Method = GET
Request URI = /api/offers
Parameters = {}
Headers = {Content-Type=[application/json]}
Body = <no character encoding set>
Session Attrs = {}
Handler:
Type =
org.springframework.web.servlet.resource.ResourceHttpRequestHandler
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 404
Error message = null
Headers = {}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status
Expected :200
Actual :404
<Click to see difference>
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:55)
at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:82)
at org.springframework.test.web.servlet.result.StatusResultMatchers.lambda$matcher$9(StatusResultMatchers.java:619)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:178)
at brozek.com.offer.OfferControllerIntegrationTest.givenOffers_whenGetOffers_thenReturnJsonArray(OfferControllerIntegrationTest.java:89)
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:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
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:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

Usually integration test setup should mock the controller created in the test Spring context with #WebMvcTest(value = OfferRestController.class). The usual syntax is:
#RunWith(SpringRunner.class)
#WebMvcTest(value = OfferRestController.class)
#AutoConfigureMockMvc
public class OfferRestControllerTest {
#MockBean
private OfferService offerService;
#Autowired
private MockMvc mvc;
}
In your test it's pointless to set Content-Type on GET request which has no body, remove
.contentType(MediaType.APPLICATION_JSON)
Starting from Spring 4.1 it's not necessary to use #Autowired on single constructor. You can simplify your code by removing #Autowired here:
public OfferServiceImpl(OfferRepository offerRepository) {
this.offerRepository = offerRepository;
}

Related

java.lang.AssertionError: Content type not set - Spring Test and Mockito

my test return failed with error:
java.lang.AssertionError: Content type not set
I read that this error don't mean so much, because return the same if there is a NPE or don't match the handler ...
But i don't understand where is the error, seem to me all ok ...
My controller is already with #RestController
This is controller Method:
#RestController
#RequestMapping("/local")
public class ControllerTest{
.....
#RequestMapping(value = "/test", method = RequestMethod.GET)
#ResponseBody
public JsonResponse<TestResponseModel> test (
#RequestParam(value = "data1", required = true) String data1,
#RequestParam(value = "data2", required = true) String data2,
{
try {
TestRequestModel input= new TestRequestModel();
input.setData1(data1);
input.setData2(data2);
TestResponseModel entities = business.test(input);
return JsonResponse(entities);
} catch (TestException e) {
log.error("APPLICATION EXCEPTION", e);
throw e;
} catch (Exception e) {
log.error("UNHANDLED EXCEPTION", e);
throw new TestException(e);
}
}
}
and this is the test:
#Mock
private Business business;
#Mock
private TestResponseModel testResponseModel;
#Test
public void getTest() throws Exception {
when(business.test(isA(TestRequestModel.class))).thenReturn(testResponseModel);
mockMvc.perform(get("/local/test")
.requestAttr("data1", "data1_test")
.requestAttr("data2", "data2_test"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().contentType("application/json"));
}
StackTrace:
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:35)
at org.springframework.test.util.AssertionErrors.assertTrue(AssertionErrors.java:65)
at org.springframework.test.web.servlet.result.ContentResultMatchers$1.match(ContentResultMatchers.java:82)
at org.springframework.test.web.servlet.MockMvc.applyDefaultResultActions(MockMvc.java:191)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:163)
at com.test.controller.TestClassTest.GetTest(TestClassTest.java:79)
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:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
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.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:68)
at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:74)
at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:161)
I fixed changing in Test Unit .requestAttr() to .param()

unit testing spring boot with mockito

So i have searched all related questions here and found no answer that worked on mine. With that being said I am trying to unit test my spring-boot application with Mockito.
Here is my controller and the function i am trying to test.
#RestController
public class UserController {
#Autowired
UserRepository userRepository;
#GetMapping("/user")
public List<User> getAllUsers() {
return userRepository.findAll();
}
#GetMapping("/user/{id}")
public User getUser(#PathVariable Integer id) {
return userRepository.findById(id).get();
}
I am trying to test getUser function
here is my Test Controller
#RunWith(SpringJUnit4ClassRunner.class)
public class UserControllerTest {
private MockMvc mockMvc;
#MockBean
private UserController userController;
#Before
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.standaloneSetup(userController).build();
}
#Test
public void getUserTest() throws Exception{
mockMvc.perform(get("/user/100").contentType(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith("application/json"))
.andExpect(jsonPath("$.role").value("deliverer"));
}
So firstly when I run this i get following error
java.lang.AssertionError: Content type not set
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:37)
at org.springframework.test.util.AssertionErrors.assertTrue(AssertionErrors.java:70)
at org.springframework.test.util.AssertionErrors.assertNotNull(AssertionErrors.java:106)
at org.springframework.test.web.servlet.result.ContentResultMatchers.lambda$contentTypeCompatibleWith$1(ContentResultMatchers.java:103)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:196)
at eldercare.RESTapi.controller.UserControllerTest.getUserTest(UserControllerTest.java:57)
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:567)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
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:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
with following data being printed
MockHttpServletResponse:
Status = 200
Error message = null
Headers = []
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
I have tested putting #ResponseBody in my Controller does not make any difference. I have also tested as stated in other post #RequestMapping(value="/user/{id}", method= RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) that doesn't work either still get the same error.
If I dont have this check .andExpect(content().contentTypeCompatibleWith("application/json")) then i get the error stating java.lang.AssertionError: No value at JSON path "$.role"
I think you should be mocking the UserRepository and not the UserController.

Spring Boot Controller Test, Null Pointer Exception

I'm learning to makes APIs. I'm trying to run a test on my Get request, but keep getting a Null Pointer Exception in my test class. What did I miss?
I'm using Spring Boot/Maven/Java 11. This is a very basic setup (as far as I know) as I have just begun to dip my toe into the world of Spring Boot.
Please see code below:
Controller Test Class:
package ControllerTest;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
public class StatControllerTest {
#Autowired
private MockMvc mockMvc;
#Test
public void testGetResponse()
throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders
.get("/get");
ResultMatcher contentMatcher = MockMvcResultMatchers.content()
.string("GET Response");
mockMvc.perform(builder).andExpect(contentMatcher).andExpect(MockMvcResultMatchers.status().isOk());
}
}
Controller Class:
package apiPackage;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
#RestController
public class StatController {
#RequestMapping("/")
public String index(){
return "Welcome to the SilverSnacks Stat Sheet!";
}
#GetMapping("/get")
public #ResponseBody ResponseEntity<String> get(){
return new ResponseEntity<String>("GET Response", HttpStatus.OK);
}
#GetMapping("/get/{id}")
public #ResponseBody ResponseEntity<String> getById(#PathVariable String id){
return new ResponseEntity<String>("GET Response:" + id, HttpStatus.OK);
}
#PutMapping("/put")
public #ResponseBody ResponseEntity<String> put(){
return new ResponseEntity<String>("PUT Response", HttpStatus.OK);
}
#PostMapping("/post")
public #ResponseBody ResponseEntity<String> post(){
return new ResponseEntity<String>("POST Response", HttpStatus.OK);
}
#DeleteMapping("/delete")
public #ResponseBody ResponseEntity<String> delete(){
return new ResponseEntity<String>("DELETE Response", HttpStatus.OK);
}
#PatchMapping("/patch")
public #ResponseBody ResponseEntity<String> patch(){
return new ResponseEntity<String>("PATCH Response", HttpStatus.OK);
}
}
Error Output:
java.lang.NullPointerException
at ControllerTest.StatControllerTest.testGetResponse(StatControllerTest.java:26)
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)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
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.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
try to add the following annotation to the StatControllerTest
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class StatControllerTest {
#Autowired
private MockMvc mockMvc;
....
}

Spring boot Autowired Service and Repository throwing nullpointerexception

I am testing a simple beginner spring boot application, but it keeps throwing NullPointerException for my service class and my repository class.
This is my controller class:
#EnableAutoConfiguration
#RestController
public class MyController {
#Autowired
private MyService service;
#GetMapping("/welcome")
public String home throws IOException {
return service.getEntities();
}
}
This is the Service class:
#EnableAutoConfiguration
#Service
public class MyService{
#Autowired(required=true)
private MyRepository repository;
public MyService() {
};
public List<Entity> getEntities() throws IOException {
return repository.findAll();
}
And this is the repository:
#Repository
public interface MyRepository extends JpaRepository<Entity, Long>{
List<Entity> findAll();
}
So, if I run the application everything is ok. The problem is when I run this test:
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = { MyService.class, MyController.class, Entity.class })
#ComponentScan("test.firstproject")
#EntityScan(basePackages = {"test.firstproject.entities"})
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#AutoConfigureTestDatabase(replace = Replace.NONE)
#EnableJpaRepositories("test.firstproject.repository")
#EnableAutoConfiguration
public class TestController {
private MockMvc mvc = MockMvcBuilders.standaloneSetup(new MyController).build();
public static final MediaType APPLICATION_JSON_UTF8 = new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8"));
#Autowired
private ObjectMapper objectMapper;
#Test
public void allEntities() {
this.objectMapper = new ObjectMapper();
try {
ResultActions resultActions = this.mvc
.perform(MockMvcRequestBuilders.get("/welcome").accept(MediaType.APPLICATION_JSON));
this.mvc.perform(get("/welcome")).andExpect(status().isOk());
MvcResult result = resultActions.andReturn();
List<Object> list = objectMapper.readValue(result.getResponse().getContentAsString(), new TypeReference<List<Entity>>(){});
for (Object c : list) {
assertTrue(c.getClass().equals(Entity.class));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
First, it threw NullPointerException when calling service.getEntities(). Then I've tried by initializing the service doing = new MyService(), but this time return repository.findAll(); throws the error. What's wrong?
EDIT - Stacktrace
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1013)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:71)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:166)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:182)
at com.example.demo.TestController.getAllEntities(TestController.java:58)
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)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
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:190)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
Caused by: java.lang.NullPointerException
at com.springmiddleware.controllers.MyController.allEntities(MyController.java:32)
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)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
... 40 more
You created MyController using new in line:
private MockMvc mvc = MockMvcBuilders.standaloneSetup(new MyController()).build();
Spring probably not injected Service to it. Try autowire:
#Autowired
private MyController myController;
And move MockMvc instantiation to #Before method:
private MockMvc mvc;
#Before
public void initialize() {
mvc = MockMvcBuilders.standaloneSetup(myController).build();
}

#WithUserDetails annotation not working for Spring Unit Test

I've got some tests written that I'm trying to run with a #WithUserDetails annotation. However, when I run it, it tells me it can't find my custom UserDetailsService implementation. How can I help the test class find this class?
Here's the stack trace for the error:
java.lang.IllegalStateException: Unable to create SecurityContext using #org.springframework.security.test.context.support.WithUserDetails(value=user1, userDetailsServiceBeanName=)
at org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener.createSecurityContext(WithSecurityContextTestExecutionListener.java:99)
at org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener.createSecurityContext(WithSecurityContextTestExecutionListener.java:81)
at org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener.beforeTestMethod(WithSecurityContextTestExecutionListener.java:60)
at org.springframework.test.context.TestContextManager.beforeTestMethod(TestContextManager.java:269)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
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.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
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.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.core.userdetails.UserDetailsService' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:353)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:340)
at org.springframework.security.test.context.support.WithUserDetailsSecurityContextFactory.createSecurityContext(WithUserDetailsSecurityContextFactory.java:53)
at org.springframework.security.test.context.support.WithUserDetailsSecurityContextFactory.createSecurityContext(WithUserDetailsSecurityContextFactory.java:39)
at org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener.createSecurityContext(WithSecurityContextTestExecutionListener.java:96)
... 31 more
This is my test class:
#RunWith(SpringJUnit4ClassRunner.class)
#WithUserDetails("user1")
public class RecipeControllerTest {
#Mock
private RecipeService recipeService;
#Mock
private CategoryService categoryService;
#Mock
private IngredientService ingredientService;
#Mock
private InstructionService instructionService;
#Mock
private UserService userService;
#InjectMocks
private RecipeController recipeController;
private MockMvc mockMvc;
#Before
public void setup() throws Exception {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("classpath:/templates/");
viewResolver.setSuffix(".html");
mockMvc = MockMvcBuilders.standaloneSetup(recipeController)
.setViewResolvers(viewResolver).build();
MockitoAnnotations.initMocks(this);
}
#Test
public void getIndex() throws Exception {
List<Category> categories = new ArrayList<>();
User user = new User();
Recipe recipe = recipeBuilder();
Recipe recipe2 = recipeBuilder();
List<Recipe> recipes = new ArrayList<>();
recipes.add(recipe);
recipes.add(recipe2);
when(userService.findByUsername("user1")).thenReturn(user);
when(recipeService.findAll()).thenReturn(recipes);
when(categoryService.findAll()).thenReturn(categories);
mockMvc.perform(MockMvcRequestBuilders.get("/"))
.andExpect(status().isOk())
.andExpect(view().name("login"));
}
}
and here is my custom UserDetailsService:
#Component
public class DetailsService implements UserDetailsService {
#Autowired
private UserService userService;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// Load user from database (throw exception if not found)
User user = userService.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User not found");
}
// Return user object
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
AuthorityUtils.createAuthorityList(user.getRoles())
);
}
}
I should mention the application has no issues finding this class when I run it normally, it's just the test class that has issues finding it.
Thanks in advance
Given you are using standaloneSetup you aren't loading an ApplicationContext thus no UserDetailsService bean exists. If you haven't already take a look at https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#test-mockmvc-securitycontextholder-rpp. You may also be interested in switching to MockMvcBuilders.webAppContextSetup

Categories