Issue with #WithUserDetails and spring boot 1.4 TestEntityManager - java

I have an issue with Spring Boot's TestEntityManager and #WithUserDetails annotation.
Here is my test suite:
public class AdvertisementAuthorizationTest extends AbstractIntegrationTest {
private static final String IMPERSONATOR_EMAIL = "joe.hacker#gmail.com";
private final static String OWNER_OF_ADVERTISEMENT_EMAIL = "john.nice#gmail.com";
#Autowired
private TestEntityManager testEntityManager;
#Autowired
private MockMvc mockMvc;
private Advertisement advertisement;
private UserAccount impersonator;
private ObjectMapper mapper = new ObjectMapper();
#Before
public void setUp() {
advertisement = testEntityManager.persist(createAdvertisement(OWNER_OF_ADVERTISEMENT_EMAIL));
impersonator = testEntityManager.persist(createUserAccount(IMPERSONATOR_EMAIL));
}
#Test
#WithUserDetails(IMPERSONATOR_EMAIL)
public void shouldNotAllowAdvertisementModification() throws Exception {
String jsonAdvertisement = mapper.writeValueAsString(advertisement);
mockMvc.perform(put("/api/advertisement/{id}", advertisement.getId())//
.contentType(MediaType.APPLICATION_JSON)//
.content(jsonAdvertisement))//
.andDo(print())//
.andExpect(status().isForbidden());//
}
#Test
#WithUserDetails(OWNER_OF_ADVERTISEMENT_EMAIL)
public void shouldAllowAdvertisementModification() throws Exception {
String jsonAdvertisement = mapper.writeValueAsString(advertisement);
mockMvc.perform(put("/api/advertisement/{id}", advertisement.getId())//
.contentType(MediaType.APPLICATION_JSON)//
.content(jsonAdvertisement))//
.andDo(print())//
.andExpect(status().isOk());//
}
}
Here is the super class:
#AutoConfigureMockMvc
#AutoConfigureTestEntityManager
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(classes = {TestApplication.class})
#WebAppConfiguration
#ActiveProfiles(Profiles.TEST)
#Transactional
public abstract class AbstractIntegrationTest {
}
When I run the tests it seems the entities are not persisted to H2 by TestEntityManager as indicated by this error message:
Hibernate: select useraccoun0_.id as id1_9_, useraccoun0_.address_id as address13_9_, useraccoun0_.email as email2_9_, useraccoun0_.email_notification as email_no3_9_, useraccoun0_.enabled as enabled4_9_, useraccoun0_.first_name as first_na5_9_, useraccoun0_.last_connection_date as last_con6_9_, useraccoun0_.password as password7_9_, useraccoun0_.registration_date as registra8_9_, useraccoun0_.role as role9_9_, useraccoun0_.token as token10_9_, useraccoun0_.user_account_type as user_ac11_9_, useraccoun0_.version as version12_9_ from user_account useraccoun0_ where useraccoun0_.email=?
22:52:39.943 [Test worker] WARN o.s.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener#43ec4dcd] to process 'before' execution of test method [public void com.bignibou.it.web.security.advertisement.AdvertisementAuthorizationTest.shouldNotAllowAdvertisementModification() throws java.lang.Exception] for test instance [com.bignibou.it.web.security.advertisement.AdvertisementAuthorizationTest#646496bc]
java.lang.IllegalStateException: Unable to create SecurityContext using #org.springframework.security.test.context.support.WithUserDetails(value=joe.hacker#gmail.com, userDetailsServiceBeanName=)
at org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener.createSecurityContext(WithSecurityContextTestExecutionListener.java:79)
at org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener.beforeTestMethod(WithSecurityContextTestExecutionListener.java:56)
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.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:112)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:56)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
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:497)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:109)
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:497)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:364)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.security.core.userdetails.UsernameNotFoundException: Username: joe.hacker#gmail.com not found!
at com.bignibou.service.security.UserAccountUserDetailsService.loadUserByUsername(UserAccountUserDetailsService.java:21)
at org.springframework.security.test.context.support.WithUserDetailsSecurityContextFactory.createSecurityContext(WithUserDetailsSecurityContextFactory.java:56)
at org.springframework.security.test.context.support.WithUserDetailsSecurityContextFactory.createSecurityContext(WithUserDetailsSecurityContextFactory.java:39)
at org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener.createSecurityContext(WithSecurityContextTestExecutionListener.java:76)
... 43 common frames omitted
Can someone please help?

This is an issue with timing with regard to TestExecutionListener callbacks and #Before test methods.
#WithUserDetails is supported by the Spring Security's WithSecurityContextTestExecutionListener which will never run after a #Before method. It is therefore impossible for Spring Security to see the user that you persist to the database in your setUp() method. That's basically what the exception is telling you: Spring Security attempted to read the user from the database before it existed.
One way to fix this is to migrate to #Sql support for inserting test data in the database. You might not find that as comfortable as simply persisting your entities, but the #Sql approach allows the test data to be created within the test-managed transaction (i.e., does not require manual clean up). Note that you will have to upgrade to Spring Security 4.1.1 in order for this to work properly.
An alternative way to address this is to persist your entities in a user-managed transaction in a #BeforeTransaction method -- for example, using Spring's TransactionTemplate. However, you will then need to manually clean up the database in an #AfterTransaction method in a similar fashion. Plus, you will still need to upgrade to Spring Security 4.1.1 in order for this to work.
Something like the following should do the trick:
#Autowired
private TestEntityManager testEntityManager;
#Autowired
PlatformTransactionManager transactionManager;
#BeforeTransaction
public void setUp() {
new TransactionTemplate(transactionManager).execute(status -> {
UserAccount owner = testEntityManager.persist(createUserAccount(OWNER_OF_ADVERTISEMENT_EMAIL));
Language language = testEntityManager.persist(createLanguage("Français"));
DayToTimeSlot dayToTimeSlot = testEntityManager.persist(createDayToTimeSlot());
advertisement = testEntityManager.persist(createAdvertisement(owner, language, dayToTimeSlot));
impersonator = testEntityManager.persist(createUserAccount(IMPERSONATOR_EMAIL));
return null;
});
}
#AfterTransaction
public void tearDown() {
new TransactionTemplate(transactionManager).execute(status -> {
testEntityManager.remove(testEntityManager.find(Advertisement.class, advertisement.getId()));
UserAccount owner = advertisement.getUserAccount();
testEntityManager.remove(testEntityManager.find(UserAccount.class, owner.getId()));
testEntityManager.remove(testEntityManager.find(UserAccount.class, impersonator.getId()));
return null;
});
}
Regards,
Sam

Related

org.mockito.exceptions.misusing.InjectMocksException: Cannot instantiate #InjectMocks

I am using #InjectMocks to inject Repository Implementation into my Test class, but it throws InjectMocksException. Below is my code and Error, please help how to resolve this error?
Error:
org.mockito.exceptions.misusing.InjectMocksException:
Cannot instantiate #InjectMocks field named 'muRepository' of type 'class com.example.MyrRepositoryImpl'.
You haven't provided the instance at field declaration so I tried to construct the instance.
However the constructor or the initialization block threw an exception : null
at org.mockito.internal.runners.DefaultInternalRunner$1$1.evaluate(DefaultInternalRunner.java:44)
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:77)
at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:83)
at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
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.MyRepositoryImpl.<init>(MyRepositoryImpl.java:27)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
Injecting:
#InjectMocks
private MyRepositoryImpl myRepository;
Test:
#Test (expected = NullPointerException.class )
public void procTest( ) throws Exception
{
when( addProc.execute( null,
null,
null
)
).thenThrow( new NullPointerException() );
myRepository.addUser( null );
}
Repository:
public class MyRepositoryImpl implements MyRepository
{
private final AddProc addProc;
#Autowired
public MyRepositoryImpl( final ProcFactory procFactory )
{
this.addProc = procFactory.create( AddProc.class ); //this is line 27 referenced in error
}
#Override
public User addUser( User user)
{
return addProc.execute(
user.getUserName( ),
user.getFirstName( ),
user.getLastName( )
);
}
}
Mockito uses the constroctor injection but you didnt use mock object for ProcFactory class.
So null pointer exception occurs. Either you have to use ProcFactory as mock in test class or, you have to add null check.
#Mock
private ProcFactory procFactory;
Regards
Having seen that you are running tests on JUnit 4, in order to initialize and inject mocks through #InjectMocks needs to use #RunWith(MockitoJUnitRunner.class) as test runner or Mockito.initMocks(this) in the setup step.
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}

Best practices on how to test a void returning method in JUnit and Spring?

I am not sure if I am testing a void returning method the correct way and also if my class-under-test (cut) requires any change in order to make it 100% testable and bug-proof.
I am seeing NullPointerException while executing the test because loginOperations is not getting set.
Error:
java.lang.NullPointerException
at com.demo.service.LoginService.doLogin(LoginService.java:40)
at com.demo.service.LoginServiceTest.doLogin(LoginServiceTest.java:25)
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.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)
LoginService.java
#Service
public class LoginService {
#Autowired
private ILoginOperations loginOperations;
public void doLogin(HttpServletRequest request, String result) {
LoginDTO loginDTO = new LoginDTO(request.getParameter("username"), result);
loginOperations.doLogin(loginDTO);
}
}
LoginServiceTest.java
public class LoginServiceTest {
private LoginService instance = new LoginService();
ILoginOperations loginOperations = Mockito.mock(ILoginOperations.class);
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
String result = "some string";
#Test
public void doLogin() {
when(request.getParameter("username")).thenReturn("johndoe");
instance.doLogin(request, result); //throws NPE while calling loginOperations.doLogin() because
assertNotNull(instance); //IS THIS THE CORRECT WAY TO TEST A VOID RETURNING METHOD ???
}
}
Now, there are 2 ways to fix the test.
I can fix the class-under-test by adding a setter method for loginOperations class and call that setter method in the test
Change #Test public void doLogin() { to #Test(expected = Exception.class) public void doLogin() {
Not sure which one is the best practice above and why.
Another Question:
Other question that I have is how to assert on a method that returns nothing. There is something like verify() but not sure how to use it.
1.You can fix the test case by adding setter method in LoginService or you can use constructor injection like -
#Autowired
public LoginService(ILoginOperations loginOperations) {
this.loginOperations = loginOperations;
}
Validating exception as #Test(expected = Exception.class) public void doLogin() is certainly not a good idea as doLogin method does not throw exception in normal circumstance.
The better way to test method with void return type is using verification API (example - mockito verification API example). You can also use Mockito's ArgumentCaptor to capture argument and assert state of that argument, along with verification API as -
#RunWith(MockitoJUnitRunner.class)
public class LoginServiceTest {
#Captor
private ArgumentCaptor<LoginDTO> captor;
#Mock
private ILoginOperations loginOperations;
#Mock
private HttpServletRequest mockServletRequest;
#InjectMocks
private LoginService loginService;
#Test
public void validateLogin() {
when(mockServletRequest.getParameter("username")).thenReturn("mock_user_name");
loginService.doLogin(mockServletRequest, "mock_result");
verify(loginOperations).doLogin(captor.capture());
LoginDTO expectedLoginDTO = captor.getValue();
assertThat(expectedLoginDTO.getResult(), is("mock_result"));
assertThat(expectedLoginDTO.getUsername(), is("mock_user_name"));
}
}
There is an excellent article from Martin Fowler about this method of testing - Mocks Aren't Stubs
actually you should create a constructor for your LoginService that gets the ILoginOperations, in this way you can create the LoginService in your test class and pass the mocked ILoginOperations as parameter, all this stuff should be done in a #Before method.
Or you can try with #InjectMocks for your LoginService and have your ILoginOperations annotated as #Mock.

How to have PersistentEntityResourceAssembler injected into request methods of custom #RepositoryRestController in a #WebMvcTest unit test

Overview
How can I have a PersistentEntityResourceAssembler properly injected into my custom REST controller's request methods during a #WebMvcTest unit test?
First SO question. Apologies in advance, probably just missing something stupid.
Sample code available on GitHub.
Oliver Gierke, where you at? :P
Details
I have a custom REST controller annotated with #RepositoryRestController. Some of its request methods have a PersistentEntityResourceAssembler injected as an argument so I can return HAL resources.
#RepositoryRestController
#RestController
#RequestMapping(produces = MediaTypes.HAL_JSON_VALUE )
public class ReportRestController {
private final ReportRepository reportRepository;
public ReportRestController(ReportRepository reportRepository) {
this.reportRepository = reportRepository;
}
#GetMapping(path = "/custom/reports/{id}")
public ResponseEntity<?> customReportsEndpoint(#PathVariable("id") Long id,
PersistentEntityResourceAssembler entityAssembler) {
return ResponseEntity.ok(entityAssembler.toResource(reportRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("No report found with ID: " + id))));
}
}
If I am running an integration test (#SpringBootTest), this works fine:
import static org.hamcrest.CoreMatchers.*;
import static org.mockito.BDDMockito.any;
import static org.mockito.BDDMockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class CustomRestControllerIntegrationTest {
private static final String REPORT_NAME = "Report 1";
#MockBean
private ReportRepository repository;
#Autowired
private MockMvc mvc;
#Test
public void thisTestPasses() throws Exception {
given(repository.findById(any())).willReturn(Optional.of(new Report(1L, REPORT_NAME, new User(1L, "pbriggs"))));
mvc.perform(get("/custom/reports/1"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.name", equalTo(REPORT_NAME)))
.andExpect(jsonPath("$._links.enteredBy").exists())
.andReturn().getResponse();
}
}
However, if I am running a unit test (#WebMvcTest), the PersistentEntityResourceAssembler cannot be constructed due to 'entities' not being injected properly.
Caused by: org.springframework.beans.BeanInstantiationException:
Failed to instantiate
[org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler]:
Constructor threw exception; nested exception is
java.lang.IllegalArgumentException: entities is marked #NonNull but
is null
Full stacktrace available in GitHub (reached character limit)
Code:
import static org.hamcrest.Matchers.*;
import static org.mockito.BDDMockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
#RunWith(SpringRunner.class)
#WebMvcTest
#EnableSpringDataWebSupport
public class CustomRestControllerUnitTest1 {
#Autowired
private MockMvc mvc;
#MockBean
private ReportRepository repository;
#Test
public void thisTestFails() throws Exception {
Report report = new Report(1L,"Report 1", new User(1L,"pbriggs"));
given(repository.findById(1L)).willReturn(Optional.of(report));
// Fails with:
//
// Caused by: org.springframework.beans.BeanInstantiationException:
// Failed to instantiate [org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler]:
// Constructor threw exception; nested exception is java.lang.IllegalArgumentException:
// entities is marked #NonNull but is null
MvcResult mvcResult = mvc.perform(get("/custom/reports/1").accept(MediaTypes.HAL_JSON_VALUE))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.name", is("Report 1")))
.andReturn();
}
}
I assume this is because RepositoryRestMvcAutoConfiguration (and thus in turn RepositoryRestMvcConfiguration) is never getting loaded. This is the correct behavior for an #WebMvcTest as it only loads web related beans (#Controller, #ControllerAdvice, #JsonComponent, Converter/GenericConverter, Filter, WebMvcConfigurer and HandlerMethodArgumentResolver).
Also, I get stack overflows about half the time running the unit tests in the sample code on GitHub. Kinda weird as it is very non-deterministic..
So to repeat, How can I have aPersistentEntityResourceAssembler properly injected into my custom REST controller's request methods during a #WebMvcTest unit test?
Requirements
This must be run in a unit test; I do not want to fire up an entire application context
The returned json payload must be a HAL formatted document (must have _links section etc.)
Research/Related Questions
1) Add #EnableSpringDataWebSupport
StackOverflow question: How do I set up unit tests for RepositoryRestController in Spring?
This question/answer recommends adding #EnableSpringDataWebSupport but this makes my controller never get instantiated. Maybe because it uses a #Configuration and a unit test doesn't run in a full container? I dunno.
Update 10/28/18: The above question also resulted in a Documentation Request being created in JIRA.
2) Change PersistentEntityResourceAssembler to a RepositoryEntityLinks
StackOverflow question: Testing a custom RepositoryRestController that uses a PersistentEntityResourceAssembler
The answer to this question recommended changing the PersistentEntityResourceAssembler to a RepositoryEntityLinks and generating the links manually. I need these links to be automatically generated as is done with the PersistentEntityResourceAssembler
3) Add #BasePathAwareController to controller
StackOverflow question: JUnit for RestController with parameter PersistentEntityResourceAssembler
One of the answers pointed me to DATAREST-657 which suggested adding #BasePathAwareController but this didn't change anything.
4) Mocking PersistentEntityResourceAssembler
StackOverflow question: Rest Controllers vs spring-data-rest RepositoryRestResource
This answer recommended mocking the PersistentEntityResourceAssembler and other stuff but I couldn't get it to work. I would get the following exception:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class org.mockito.internal.junit.DefaultStubbingLookupListener]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.mockito.internal.junit.DefaultStubbingLookupListener and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.data.rest.webmvc.PersistentEntityResource["persistentEntity"]->org.springframework.data.mapping.PersistentEntity$MockitoMock$2115290768["mockitoInterceptor"]->org.mockito.internal.creation.bytebuddy.MockMethodInterceptor["mockHandler"]->org.mockito.internal.handler.InvocationNotifierHandler["mockSettings"]->org.mockito.internal.creation.settings.CreationSettings["stubbingLookupListeners"]->java.util.ArrayList[0])
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:71)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
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:165)
at com.prestonb.edu.CustomRestControllerUnitTest2.thisTestFails(CustomRestControllerUnitTest2.java:78)
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.mockito.internal.junit.JUnitRule$1.evaluateSafely(JUnitRule.java:52)
at org.mockito.internal.junit.JUnitRule$1.evaluate(JUnitRule.java:43)
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)
Caused by: org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class org.mockito.internal.junit.DefaultStubbingLookupListener]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.mockito.internal.junit.DefaultStubbingLookupListener and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.data.rest.webmvc.PersistentEntityResource["persistentEntity"]->org.springframework.data.mapping.PersistentEntity$MockitoMock$2115290768["mockitoInterceptor"]->org.mockito.internal.creation.bytebuddy.MockMethodInterceptor["mockHandler"]->org.mockito.internal.handler.InvocationNotifierHandler["mockSettings"]->org.mockito.internal.creation.settings.CreationSettings["stubbingLookupListeners"]->java.util.ArrayList[0])
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:291)
at org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:102)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:272)
at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:224)
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:82)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:119)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:891)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
... 34 more
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.mockito.internal.junit.DefaultStubbingLookupListener and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.data.rest.webmvc.PersistentEntityResource["persistentEntity"]->org.springframework.data.mapping.PersistentEntity$MockitoMock$2115290768["mockitoInterceptor"]->org.mockito.internal.creation.bytebuddy.MockMethodInterceptor["mockHandler"]->org.mockito.internal.handler.InvocationNotifierHandler["mockSettings"]->org.mockito.internal.creation.settings.CreationSettings["stubbingLookupListeners"]->java.util.ArrayList[0])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1191)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:312)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:71)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:33)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:119)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:79)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:18)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1396)
at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:913)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:285)
... 45 more
org.springframework.data.rest.webmvc.PersistentEntityResource["persistentEntity"]
->org.springframework.data.mapping.PersistentEntity$MockitoMock$1659608278["mockitoInterceptor"]
->org.mockito.internal.creation.bytebuddy.MockMethodInterceptor["mockHandler"]
->org.mockito.internal.handler.InvocationNotifierHandler["mockSettings"]
->org.mockito.internal.creation.settings.CreationSettings["stubbingLookupListeners"]
->java.util.ArrayList[0])
Code:
import static org.hamcrest.CoreMatchers.*;
import static org.mockito.BDDMockito.any;
import static org.mockito.BDDMockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
public class CustomRestControllerUnitTest2 {
#Mock
private PersistentEntityResourceAssembler assembler;
#Mock
private PersistentEntityResourceAssemblerArgumentResolver assemblerResolver;
#Mock
private PersistentEntity<Report, ?> entity;
#InjectMocks
private ReportRestController controller;
private MockMvc mvc;
#Rule
public MockitoRule rule = MockitoJUnit.rule();
#Mock
private ReportRepository repository;
#Before
public void setup() {
this.mvc = MockMvcBuilders.standaloneSetup(controller)
.setCustomArgumentResolvers(assemblerResolver)
.build();
}
#Test
public void thisTestFails() throws Exception {
Report report = new Report(1L,"Report 1", new User(1L,"pbriggs"));
given(repository.findById(1L)).willReturn(Optional.of(report));
given(assemblerResolver.supportsParameter(any())).willReturn(true);
given(assemblerResolver.resolveArgument(any(), any(), any(), any())).willReturn(assembler);
given(assembler.toResource(report)).willReturn(PersistentEntityResource.build(report, entity).build());
MvcResult mvcResult = mvc.perform(get("/custom/reports/1").accept(MediaTypes.HAL_JSON_VALUE))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.name", is("Report 1")))
.andExpect(jsonPath("$.name").exists())
.andExpect(jsonPath("$._links.enteredBy").exists())
.andReturn();
}
}
So then I added a custom argument resolver to the MockMvc which fixed that issue but my JSON was no longer being formatted properly as HAL:
#Test
public void thisTestFails() throws Exception {
Report report = new Report(1L,"Report 1", new User(1L,"pbriggs"));
given(repository.findById(1L)).willReturn(Optional.of(report));
given(assemblerResolver.supportsParameter(any())).willReturn(true);
given(assemblerResolver.resolveArgument(any(), any(), any(), any())).willReturn(assembler);
given(assembler.toResource(report)).willReturn(PersistentEntityResource.build(report, entity).build());
MvcResult mvcResult = mvc.perform(get("/custom/reports/1").accept(MediaTypes.HAL_JSON_VALUE))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.name", is("Report 1")))
.andExpect(jsonPath("$.name").exists())
// Fails:
//
// Caused by: com.jayway.jsonpath.PathNotFoundException: Missing property in path $['_links']
.andExpect(jsonPath("$._links.enteredBy").exists())
.andReturn();
/*
* Expected (HAL document):
*
* {
* "name" : "Report 1",
* "_links" : {
* "self" : {
* "href" : "http://localhost/reports/1"
* },
* "report" : {
* "href" : "http://localhost/reports/1"
* },
* "enteredBy" : {
* "href" : "http://localhost/reports/1/enteredBy"
* }
* }
* }
*
* Actual (Normal json):
*
* {
* "id": 1,
* "name": "Report 1",
* "enteredBy": {
* "id": 1,
* "username": "pbriggs"
* }
* // plus a bunch of mockito properties
* }
*/
}

Nullpointer exception on constructor injection and works with field injection mockito

I have an abstract class which has a dependency which is being autowired:
public abstract class ClassB {
#Autowired
private ClassC classC;
public String getValue() {
classC.getSomeMethod();
}
}
I've a class which extends this abstract class:
#Component
public class ClassA extends ClassB {
#Autowired
private ClassD classD;
public String getClassAMethod() {
String value = getValue();
String dReturn = classD.getD();
return value + dReturn;
}
}
Now while doing UnitTesting I can do:
public class ClassATest {
#Mock
private ClassC classC;
#Mock
private ClassD classD;
#InjectMocks
private ClassA classA;
#Test
public void testSomething() {
when(classC.getSometMethod()).thenReturn("classC");
when(classD.getD()).thenReturn("classD");
assertEquals(classA.getClassAMethod(), "classCclassD");
}
}
This works fine, however if I use constructor injection for ClassA I get a Null pointer exception for classC.
#Component
#RequiredArgsConstructor(onConstructor = #__(#Autowired))
public class ClassA extends ClassB {
private final ClassD classD;
public String getClassAMethod() {
String value = getValue();
String dReturn = classD.getD();
return value + dReturn;
}
}
In the second case I even tried replacing InjectMocks with a normal constructor invocation, but ClassC object doesn't get mocked.
Stack trace:
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(Unknown Source)
at org.mockito.internal.runners.DefaultInternalRunner.run(Unknown Source)
at org.mockito.internal.runners.StrictRunner.run(Unknown Source)
at org.mockito.junit.MockitoJUnitRunner.run(Unknown Source)
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)
Lombok's #AllArgsConstructor and #RequiredArgsConstructor only cover fields that are declared in the class itself. Fields from superclasses are not considered, as lombok cannot access those classes, because they are not yet resolved at the time lombok runs during the compilation process.
As a result in your case, the constructor that is generated for ClassA only has ClassD classD as argument, but not ClassC classC. (You can see that in the class outline view of your IDE, or by delomboking your code.) Therefore, classC remains uninitialized, causing the NPE.
So lombok cannot help you in your case, unfortunately. You have to write your constructor manually.

Spring Controller Integration Testing using TestNg

I am new to Spring unit Testing. Writing test cases for the Spring rest Controller. When I am writing the test cases in this way
#WebAppConfiguration
#ContextConfiguration(locations = {"file:src/test/resources/applicationContext.xml"})
public class TaskControllerIntegrationTest extends AbstractTransactionalTestNGSpringContextTests {
private MockMvc mockMvc;
#Autowired
private WebApplicationContext wac;
#BeforeClass
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
#Test
public void testGetAllTasks() throws Exception {
mockMvc.perform(get("/v1/testSessions/{testSessionId}/tasks", 1l))
.andExpect(status().isOk());
}
}
I am getting the testcase failed don't know why :( while If i initialize the MockMvc using the standalone controller it works perfect and my allTest cases are passes.The setup for the MockMvc using standalone controller is in this way. It's for unit testing:
#Mock
private TaskService taskServiceMock;
#InjectMocks
private TaskController taskController;
private MockMvc mockMvc;
#Spy
List<Task> allTasks = new ArrayList<Task>();
/* #Spy
List<TaskSessionModel> taskSessionModelList = new ArrayList<TaskSessionModel>();*/
#BeforeClass
public void setUp() {
// Mockito.reset(taskServiceMock);
MockitoAnnotations.initMocks(this);
// taskSessionModelList = getAllTaskSessionModels();
allTasks = getAllTasks();
this.mockMvc = MockMvcBuilders.standaloneSetup(taskController).build();
}
#Test
public void testGetAllTasks() throws Exception {
// when(taskSessionDao.findAllByTestSession(1l)).thenReturn(taskSessionModelList);
when(taskServiceMock.getAllTasks(1l)).thenReturn(allTasks);
mockMvc.perform(get("/v1/testSessions/{testSessionId}/tasks", 1l)
.accept(MediaType.APPLICATION_JSON_VALUE))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$[0].name", is("Average")));
List<Task> expTaskList = taskController.getAllTasks(1l);
verify(taskServiceMock, times(2)).getAllTasks(1l);
verifyNoMoreInteractions(taskServiceMock);
assertEquals(allTasks, expTaskList);
}
But if i write the same unit test by using the WebApplicationContext .. I will get error and test cases will failed :
java.lang.AssertionError: Status
Expected :200
Actual :500
<Click to see difference>
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:60)
at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:89)
at org.springframework.test.web.servlet.result.StatusResultMatchers$10.match(StatusResultMatchers.java:654)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:152)
at com.blueoptima.dt.controller.TaskControllerIntegrationTest.testGetAllTasks(TaskControllerIntegrationTest.java:46)
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.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
at org.testng.internal.MethodInvocationHelper$1.runTestMethod(MethodInvocationHelper.java:200)
at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.run(AbstractTestNGSpringContextTests.java:171)
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.testng.internal.MethodInvocationHelper.invokeHookable(MethodInvocationHelper.java:212)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:707)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
at org.testng.SuiteRunner.run(SuiteRunner.java:240)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
at org.testng.TestNG.run(TestNG.java:1057)
at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:74)
at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:124)
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 com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
I don't know what's the wrong? I tried almost all the solution for the WebApplicationContext setup(see the first code) it's in the same way as I see .. on this website and mostly configuration in spring official website and other after googling it but still error remains same?
Have a look into this ! Cheers !!
Go back one step, forget about all Spring and technology stuff and ask yourself what you want to achieve with the tests?
If you want to do a real integration tests, don't mock controllers or services, so the following code makes no sense:
#Mock
private TaskService taskServiceMock;
That should be the problem in your setup. Remove all mocks instead of MockMvc and try again. Take a cup of coffee and read the official documentation, it will teach you all the details including setting up a in-memory-database and setting up the Spring TestContext Framework.
To access your controllers, you have two choices, depending on how deep the tests shall go.

Categories