How do I verify two consecutive calls to a mock service in my JUnit test with mockito? - spring

I'm using Spring 4.3.8.RELEASE, JUnit 4.12 ,and Mockito 1.10.18. I'm trying to test whether my "publishEvent" method is called from below ...
#Service
#Transactional
public class MyObjectServiceImpl implements MyObjectService, ApplicationEventPublisherAware
{
private ApplicationEventPublisher publisher;
#Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher)
{
this.publisher = publisher;
}
...
public void myMethod(MyObject obj) {
...
publisher.publishEvent(new ThirdPartyUpdateUserEvent(userId));
publisher.publishEvent(new ThirdPartyUpdateObjectEvent(objectId));
and then in my JUnit test I have
#Before
public final void setup()
{
eventPublisher = Mockito.mock(ApplicationEventPublisher.class);
((ApplicationEventPublisherAware) myObjectService).setApplicationEventPublisher(eventPublisher);
((ApplicationEventPublisherAware) userService).setApplicationEventPublisher(eventPublisher);
} // setup
#Test
...
// Verify first call
final ArgumentCaptor<ThirdPartyUpdateUserEvent> argument2 = ArgumentCaptor.forClass(ThirdPartyUpdateUserEvent.class);
Mockito.verify(eventPublisher, Mockito.times(2)).publishEvent(argument2.capture());
Assert.assertEquals("Failed to call method with proper argument.", userId, argument2.getValue().getUserId());
// Verify second call
final ArgumentCaptor<ThirdPartyUpdateMyObjectEvent> argument = ArgumentCaptor.forClass(ThirdPartyUpdateMyObjectEvent.class);
Mockito.verify(eventPublisher, Mockito.times(2)).publishEvent(argument.capture());
Assert.assertEquals("Failed to call method with proper argument.", objectId, argument.getValue().getObjectId());
Through debugging, I can see that each of the "publishEvent" methods is called exactly once, yet when I go to verify the calls I get the error for the first "verify" line in my #Test
java.lang.ClassCastException: org.mainco.subco.ThirdPartyItem.domain.ThirdPartyUpdateMyObjectEvent cannot be cast to org.mainco.subco.ThirdPartyItem.domain.ThirdPartyUpdateUserEvent
at com.follett.fdr.lycea.lms.MyObject.test.service.MyObjectServiceDWRTest.testArchiveMyObject(MyObjectServiceDWRTest.java:1234)
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.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.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
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.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)
What's the right way to verify two consecutive calls to my mocked publish service?

Instead of creating an ArgumentCaptor for ThirdPartyUpdateUserEvent and
ThirdPartyUpdateMyObjectEvent, why not create one captor for Object:
final ArgumentCaptor<Object> argumentsCaptor = ArgumentCaptor.forClass(Object.class);
Or better yet, whatever common interface ThirdPartyUpdateUserEvent and ThirdPartyUpdateMyObjectEvent implement (ThirdPartyUpdateEvent?)
Now you can do this:
Mockito.verify(eventPublisher, Mockito.times(2)).publishEvent(argumentsCaptor.capture());
List<Object> arguments = argumentsCaptor.getAllValues();
assertTrue(arguments.get(0) instanceof ThirdPartyUpdateUserEvent);
assertTrue(arguments.get(1) instanceof ThirdPartyUpdateMyObjectEvent);
And test those arguments for whatever other conditions you need.

Related

Can't stub SimpleMessageListenerContainer isActive method [Spring AMQP Rabbit]

I'm trying to create unit tests for my Spring EventListeners that toggle SimpleMessageListenerContainer (start/stop).
The code I'm trying to test:
#Configuration
public class SpringEventsListeners {
private static CPLocation cpLocation = CPLoggingFactory.createCPLocation(SpringEventsListeners.class);
private ConfigurationServiceImpl configService;
//Constructor Injection for Testability.
public SpringEventsListeners(final ConfigurationServiceImpl configService) {
this.configService = configService;
}
/**
* Rabbit listeners might be started/stopped after a refresh depending on a property.
* In case a change is needed, we perform it.
*/
#EventListener(classes= { ApplicationReadyEvent.class, EnvironmentChangeEvent.class })
public void handleRabbitListenerToggle() {
String method = "handleRabbitListenerToggle";
cpLocation.info(method, "Received refresh event. Determining action.");
boolean shouldActivateRabbit = configService.shouldActivateRabbitListeners();
for (SimpleMessageListenerContainer container : configService.getAllRabbitSimpleMessageListenerContainers()) {
if (shouldActivateRabbit && !container.isActive()) {
container.start();
cpLocation.info(method, "Starting container: "+Arrays.toString(container.getQueueNames()));
}
else if (!shouldActivateRabbit && container.isActive()) {
container.shutdown();
cpLocation.info(method, "Shutting down container: "+Arrays.toString(container.getQueueNames()));
}
}
}
}
Minimal test (tests nothing):
#RunWith(MockitoJUnitRunner.class)
public class SpringEventsListenersTests {
#InjectMocks
private SpringEventsListeners classUnderTest;
#Mock
private ConfigurationServiceImpl mockConfigurationService;
#Mock
private SimpleMessageListenerContainer mockSimpleMessageListenerContainer;
#Test
public void testToggleTrue() {
//Given
given(mockConfigurationService.shouldActivateRabbitListeners()).willReturn(true);
given(mockConfigurationService.getAllRabbitSimpleMessageListenerContainers()).willReturn(Arrays.asList(mockSimpleMessageListenerContainer));
given(mockSimpleMessageListenerContainer.isActive()).willReturn(false);
//When
classUnderTest.handleRabbitListenerToggle();
Assert.assertThat(true, is(true));
}
}
The tests won't run as I receive a NullPointerException on given(mockSimpleMessageListenerContainer.isActive()).willReturn(false);:
java.lang.NullPointerException at
org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.isActive(AbstractMessageListenerContainer.java:1271)
at
com.cp.order.listener.SpringEventsListenersTests.testToggleTrue(SpringEventsListenersTests.java:36)
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.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:79)
at
org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:85)
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: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)
I will also need to assert that .shutdown or .start were called on the container, so it needs to be mocked.
Mockito can't mock final methods (isActive() is final).
You could use reflection (e.g. DirectFieldAccessor) to check the active field instead.
That said, mocking the listener container is rather unusual; it is a complex piece of code; perhaps you could explain exactly what you are trying to test?

CompletableFuture and MockMVC

I am using SpringBoot 2.0.6-RELEASE
When I configure my api to use a CompletableFuture with no executor service provided - my tests run successfully. For example this tests passes ok
public Future<List<AlertsBodyVO>> getAlerts(#PathVariable(value = "userId") final String userId) {
return CompletableFuture.supplyAsync(() -> Service.getAlerts(userId));
}
#Test
public void testGetAlerts_NullResult() throws Exception {
String userId = "123456";
List<AlertsBodyVO> alertsVOList = null;
Mockito.when(mockService.getAlerts(Mockito.anyString())).thenReturn(alertsVOList);
MvcResult result = this.mockMvc.perform(get("/alerts/{userId}", userId)).andExpect(status().isOk())
.andReturn();
mockMvc.perform(asyncDispatch(result)).andExpect(status().isOk())
.andExpect(jsonPath("$").doesNotExist())
.andReturn();
Mockito.verify(mockService, Mockito.times(1)).getAlerts(Mockito.anyString());
}
However - when I define my api to use an executorService as follows
public Future<List<AlertsBodyVO>> getAlerts(#PathVariable(value = "userId") final String userId) {
return CompletableFuture.supplyAsync(() -> Service.getAlerts(userId), executorService);
}
I get the following error
java.lang.IllegalStateException: Async result for handler [public java.util.concurrent.Future<java.util.List<com.domain.AlertsBodyVO>> com.controllers.API.getAlerts(java.lang.String)] was not set during the specified timeToWait=10000
at org.springframework.test.web.servlet.DefaultMvcResult.getAsyncResult(DefaultMvcResult.java:146)
at org.springframework.test.web.servlet.DefaultMvcResult.getAsyncResult(DefaultMvcResult.java:136)
at org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch(MockMvcRequestBuilders.java:269)
at com.controllers.APITest.testGetAlerts_NullResult(APITest.java:207)
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.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
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:78)
at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:84)
at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:161)
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)
Any idea how I can get my MockMvc tests to pass when I specify the executorService to use?
It is difficult to used Mocked ExecuterService, because you should also mock all their behavior, like
Mockito.when(mockedExecuterService.execute...
And another hidden calls and processes inside of executor service.
Instead of that you can just create simple single thread executor for test purpose, i checked and it work correct with real ExecutorService (for example Executors.newSingleThreadExecutor()) and failed ofcouse with mocked. I think you now it how create test context - Spring Test Context

Whether LettuceConnectionFactory have version restrictions on redis and springboot?

The project need a custom RedisConnectionFactory and finds a problem:
when using LettuceConnectionFactory, the runtime always reports java.lang.NullPointerException, while JedisConnectionFactory can pass tests.
I think that whether LettuceConnectionFactory have version restrictions on redis and springboot?
Developing environment:
Springboot: 2.1.0.release
redis:3.2.8
jdk8.
Java Code
#Component
#Configuration
public class RedisConfig {
public LettuceConnectionFactory lettuceConnectionFactoryTest(){
return new LettuceConnectionFactory(new RedisStandaloneConfiguration("127.0.0.1", 6379));
}
public JedisConnectionFactory jedisConnectionFactoryTest(){
return new JedisConnectionFactory(new RedisStandaloneConfiguration("127.0.0.1", 6379));
}
}
Test Code
#Autowired
private RedisConfig redisConfig;
#Autowired
private StringRedisTemplate redisTemplate;
#Test
public void test(){
redisTemplate.setConnectionFactory(redisConfig.lettuceConnectionFactoryTest());
ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
valueOperations.set("test", "test123");
System.out.println(valueOperations.get("test"));
}
Exception
java.lang.NullPointerException
at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getNativeConnection(LettuceConnectionFactory.java:1085)
at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getConnection(LettuceConnectionFactory.java:1065)
at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getSharedConnection(LettuceConnectionFactory.java:865)
at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getConnection(LettuceConnectionFactory.java:340)
at org.springframework.data.redis.core.RedisConnectionUtils.doGetConnection(RedisConnectionUtils.java:132)
at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:95)
at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:82)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:211)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:184)
at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:95)
at org.springframework.data.redis.core.DefaultValueOperations.set(DefaultValueOperations.java:236)
at com.test.infrastructure.InfrastructureApplicationTests.test(InfrastructureApplicationTests.java:40)
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: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.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)
The NullPointerException is occurring because LettuceConnectionFactory has not been initialised. It should be initialised by Spring Framework calling afterPropertiesSet() which is one of the standard bean lifecycle methods. That method isn't being called as your LettuceConnectionFactory isn't a bean due to a missing #Bean annotation on RedisConfig.lettuceConnectionFactoryTest().
Adding #Bean on RedisConfig.lettuceConnectionFactoryTest() should solve your problem. It will also allow you to inject LettuceConnectionFactory directly (into an #Autowired field in your test) rather than injecting RedisConfig and then calling lettuceConnectionFactoryTest() on it.

Same MongoDb query method... opposite testing result?

I've a MongoDb repository with a query to find a document by its Id field (which also has #Id annotation).
public interface CustomerRepository extends MongoRepository<Customer,
String> {
public Customer findById(String id);
}
What I don`t understand is why this is correct when testing the repository
#Test
public void testFindById() {
this.customerRepository.save(new Customer("4", "Anna", "Michigan"));
assertNotNull(customerRepository.findById("4"));
}
but when testing the controller whose method use the findById() method
#Controller
public class CustomerController {
#Autowired
private CustomerRepository customerRepository;
public boolean existsId(String id) {
return this.customerRepository.findById(id) != null;
}
}
I get an AssertionError
#RunWith(SpringRunner.class)
#SpringBootTest
#TestPropertySource(locations = "classpath:test.properties")
public class CustomerControllerIT {
#Autowired
private CustomerController customerController;
#Test
public void testExistsIdTrue() {
CustomerDto customerDto = new CustomerDto("2", "Mark", "New York");
assertTrue(customerController.existsId("2"));
}
}
I cannot understand why that happens, when in respository and controller we are using the same method.
This is the trace:
java.lang.AssertionError
at org.junit.Assert.fail(Assert.java:86)
at org.junit.Assert.assertTrue(Assert.java:41)
at org.junit.Assert.assertTrue(Assert.java:52)
at account.persistence.controllers.CustomerControllerIT.testExistsIdTrue(CustomerControllerIT.java:32)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
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.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: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.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:538)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)

Testing a spring mvc rest controller

I'm trying to create a very basic unit test for a spring mvc rest controller using the MockMvcBuilders.standaloneSetup method. I keep getting a 404 error. Below I list my Test application context, my test class, and my controller and the full stack trace. Any guidance is appreciated.
#Configuration
public class TestContext
{
#Bean
public Service service()
{
return mock(Service.class);
}
}
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes={TestContext.class})
#WebAppConfiguration
public class TestUsingWebAppContextSetUp
{
private MockMvc mockMvc;
#Autowired
private Service service;
#Before
public void setUp()
{
mockMvc = MockMvcBuilders.standaloneSetup(MyController.class)
.build();
}
#Test
public void test() throws Exception
{
mockMvc.perform(get("/search?phoneNumber=5551112222"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE));
}
}
public class MyController
{
#Autowired
private Service service;
#RequestMapping("/search")
public List<SearchResult> search(#RequestParam(value="phoneNumber") String phoneNumber)
{
System.out.println("search called");
Search search = new Search();
search.setPhoneNumber(phoneNumber);
return service.search(search);
}
}
java.lang.AssertionError: Status expected:<200> but was:<404> 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:653)
at
org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:152)
at
com.mycompany.TestUsingWebAppContextSetUp.test(TestUsingWebAppContextSetUp.java:41)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at
java.lang.reflect.Method.invoke(Unknown Source) 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.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:73)
at
org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
at
org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:73)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at
org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:217)
at
org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83)
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:68)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at
org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163)
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:675)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
The javadoc of MockMvcBuilders.standaloneSetup states
Build a MockMvc by registering one or more #Controller's instances and
configuring Spring MVC infrastructure programmatically. This allows
full control over the instantiation and initialization of controllers,
and their dependencies, similar to plain unit tests while also making
it possible to test one controller at a time.
So you would use it as
mockMvc = MockMvcBuilders.standaloneSetup(new MyController()).build();
registering an actual instance. If you need this to be a Spring managed instance (which you probably do considering it has an #Autowired field), you'd have to get it from the ApplicationContext.

Resources