I am using Spring Boot REST and Mockito. How can I write a test case?
Error:
java.lang.NullPointerException
at java.util.concurrent.ConcurrentHashMap.putVal(ConcurrentHashMap.java:1011)
at java.util.concurrent.ConcurrentHashMap$KeySetView.add(ConcurrentHashMap.java:4595)
at com.mastercard.customer.data.management.refdata.service.RegionService.lambda$2(RegionService.java:58)
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:174)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.stream.Streams$StreamBuilderImpl.forEachRemaining(Streams.java:419)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at com.mastercard.customer.data.management.refdata.service.RegionService.findAllRegions(RegionService.java:49)
at com.mastercard.customer.data.management.refdata.service.RegionServiceTest.findAllRegions_SuccessTest(RegionServiceTest.java:68)
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.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:74)
at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:80)
at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.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: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)
Code
public List<Employee> findAllEmployees() {
List<Object> obj = mongoTemplate.query(Department.class).distinct("employees").all();
List<Employee> employees = null;
if (!CollectionUtils.isEmpty(obj)) {
employees = obj.stream().map(e -> (Employee) e).filter(distinctByKey(Employee::getEmployeeCd)).collect(Collectors.toList());
}
return employees;
}
public <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return t -> seen.add(keyExtractor.apply(t));
}
Test case
#Test
public void findEmp() {
when(mongoTemplate.query(Department.class)).thenReturn(executableDepartment);
when(mongoTemplate.query(Department.class).distinct("employees")).thenReturn(distinctDepartment);
when(mongoTemplate.query(Department.class).distinct("employees").all()).thenReturn(obj);
when(obj.stream()).thenReturn(Stream.of(obj));
when(obj.stream().map(e -> (Region) e).thenReturn(Stream.of(region));
assertNotNull(empService.findAllRegions());
}
1) Try to set up you mocking one by one instead of cascading the calls:
when(mongoTemplate.query(Department.class)).thenReturn(executableDepartment);
when(executableDepartment).distinct("employees")).thenReturn(distinctDepartment);
when(distinctDepartment.all()).thenReturn(obj);
The executableDepartment and distinctDepartment need to be mocks as well of course.
2) Do not mock the List interface. Feed it with pre-configured data and allow the SUT to work on it as it is. Sp mocking should only be used in this part:
mongoTemplate.query(Department.class).distinct("employees").all();
So the part that provides data. But leave the actual logic to run as it is.
I migrated to Spring 2.X from 1.X and some errors occured. I can not handle this one.
(EDIT BELOW)
I tried both with when... and with doReturn , none of these works.
Method I want to unit-test:
#Service
public class BookRentalService {
private final AccountRepository accountRepository;
private final BookRepository bookRepository;
private final BookRentalsRepository bookRentalsRepository;
#Autowired
public BookRentalService(BookRepository bookRepository, BookRentalsRepository bookRentalsRepository, AccountRepository accountRepository) {
this.bookRepository = bookRepository;
this.bookRentalsRepository = bookRentalsRepository;
this.accountRepository = accountRepository;
}
public String rentBook(int accountID, int bookID) {
Account account = accountRepository.findById(accountID)
.orElseThrow(() -> new IllegalArgumentException("Account does not exist!"));
if (account.getAmountOfCashToPay() == 0) {
if (bookRepository.doesBookExistsWithGivenID(bookID)) {
Book bookToRent = bookRepository.findById(bookID)
.orElseThrow(() -> new IllegalArgumentException("Book does not exist!"));
if (bookToRent.isAvailable()) {
updateBookAvailabilityAndSaveToDb(bookToRent);
BookRentals preparedBookToRent = prepareBookToRent(accountID, bookToRent);
bookRentalsRepository.save(preparedBookToRent);
} else {
throw new IllegalArgumentException("Book is not available");
}
}
} else {
throw new IllegalArgumentException("Please go to paypenalty/accountID to settle the arrears, otherwise you can not rent more books!");
}
return "Book was rented";
}
Unit-test
#RunWith(MockitoJUnitRunner.class)
public class BookRentalServiceTest {
#Mock
public BookRentalsRepository bookRentalsRepository;
#Mock
public BookRepository bookRepository;
#Mock
public AccountRepository userRepository;
#InjectMocks
public BookRentalService bookRentalService;
#Test(expected = IllegalArgumentException.class)
public void rentBookWhenAccountNotExists() {
Book book = createDummyBook();
Account user = createDummyUser();
//when(bookRepository.doesBookExistsWithGivenID(book.getId())).thenReturn(true);
//when(bookRepository.findById(book.getId()).orElse(null)).thenReturn(book);
//when(userRepository.doesAccountExistsWithGivenID(user.getId())).thenReturn(false);
doReturn(book).when(bookRepository).findById(book.getId()).orElse(null);
doReturn(true).when(bookRepository).doesBookExistsWithGivenID(book.getId());
doReturn(false).when(userRepository).doesAccountExistsWithGivenID(user.getId());
String expected = "Account does not exist";
assertEquals(expected, bookRentalService.rentBook(user.getId(), book.getId()));
}
}
Stacktrace:
java.lang.Exception: Unexpected exception, expected<java.lang.IllegalArgumentException> but was<org.mockito.exceptions.misusing.WrongTypeOfReturnValue>
at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:28)
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)
Caused by: org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
Book cannot be returned by findById()
findById() should return Optional
***
If you're unsure why you're getting above error read on.
Due to the nature of the syntax above problem might occur because:
1. This exception *might* occur in wrongly written multi-threaded tests.
Please refer to Mockito FAQ on limitations of concurrency testing.
2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies -
- with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.
at bookrental.service.book.rentals.BookRentalServiceTest.rentBookWhenAccountNotExists(BookRentalServiceTest.java:71)
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:564)
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.ExpectException.evaluate(ExpectException.java:19)
... 18 more
//EDIT
With Timothy some help. Code looks like this.
#Test(expected = IllegalArgumentException.class)
public void rentBookWhenAccountNotExists() {
Book book = createDummyBook();
Account user = createDummyUser();
when(bookRepository.doesBookExistsWithGivenID(book.getId())).thenReturn(true);
when(bookRepository.findById(book.getId()).orElse(null)).thenReturn(book);
when(userRepository.doesAccountExistsWithGivenID(user.getId())).thenReturn(false);
//doReturn(book).when(bookRepository).findById(book.getId()).orElse(null);
//doReturn(true).when(bookRepository).doesBookExistsWithGivenID(book.getId());
// doReturn(false).when(userRepository).doesAccountExistsWithGivenID(user.getId());
bookRentalService.rentBook(user.getId(), book.getId());
}
and Stack:
java.lang.Exception: Unexpected exception, expected<java.lang.IllegalArgumentException> but was<org.mockito.exceptions.misusing.WrongTypeOfReturnValue>
at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:28)
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)
Caused by: org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
Book cannot be returned by findById()
findById() should return Optional
***
If you're unsure why you're getting above error read on.
Due to the nature of the syntax above problem might occur because:
1. This exception *might* occur in wrongly written multi-threaded tests.
Please refer to Mockito FAQ on limitations of concurrency testing.
2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies -
- with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.
at bookrental.service.book.rentals.BookRentalServiceTest.rentBookWhenBookNotExist(BookRentalServiceTest.java:53)
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:564)
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.ExpectException.evaluate(ExpectException.java:19)
... 18 more
This line is wrong:
when(bookRepository.findById(book.getId()).orElse(null)).thenReturn(book);
orElse() isn't a method on your mock object, it's a method belonging to Optional... The line should be:
when(booRepository.findById(book.getId())).thenReturn(Optional.of(book));
Need help resolving error:
kotlin.UninitializedPropertyAccessException: lateinit property ultraService has not been initialized
at com.example.ultrasonic.service.UltraServiceTest.get all Ultra(UltraServiceTest.kt:39)
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.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)
service class:
https://github.com/swapab/ultrasonic/blob/master/src/main/kotlin/com/example/ultrasonic/service/UltraService.kt
package com.example.ultrasonic.service
import com.example.ultrasonic.domain.Ultra
import com.example.ultrasonic.repository.UltraRepository
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
#Service
class UltraService {
#Autowired
private lateinit var UltraRepository: UltraRepository
fun publish(Ultra: Ultra): Ultra =
UltraRepository.save(Ultra)
fun all(): List<Ultra> =
UltraRepository.findAll()
}
service class test:
https://github.com/swapab/ultrasonic/blob/master/src/test/kotlin/com/example/ultrasonic/service/UltraServiceTest.kt
package com.example.ultrasonic.service
import com.example.ultrasonic.domain.Ultra
import com.example.ultrasonic.repository.UltraRepository
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
import org.mockito.Mockito
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.test.context.ContextConfiguration
import java.time.LocalDate
#ContextConfiguration(classes = [UltraService::class])
class UltraServiceTest {
#Autowired
lateinit var ultraService: UltraService
#Mock
lateinit var UltraRepository: UltraRepository
lateinit var sampleUltra: Ultra
lateinit var sampleUltraJsonString: String
private val mapper = jacksonObjectMapper()
#Before
fun setUp() {
sampleUltra = Ultra(1,
"latest sample Ultra")
sampleUltraJsonString = mapper.writeValueAsString(sampleUltra)
}
#Test
fun `get all Ultra`() {
Mockito.doReturn(listOf(sampleUltra)).`when`(ultraService).all()
ultraService.all()
Mockito.verify(UltraRepository).findAll()
}
}
The reproducer is here: https://github.com/swapab/ultrasonic
Have you tried annotating your test class to use the SpringRunner unit test harness?
#RunWith(SpringRunner.class)
class UltraServiceTest {
}
See http://www.baeldung.com/spring-boot-testing
I have following method in my service to mock AWS sqs
#Override
public Message recieveMessage(String queueUrl) {
Objects.requireNonNull(queueUrl);
ReceiveMessageRequest request = new ReceiveMessageRequest().withQueueUrl(queueUrl).withMaxNumberOfMessages(1);
ReceiveMessageResult receiveMessageResult = this.sqsClient.receiveMessage(request);
// As per the spec, we need to return only one message.
return receiveMessageResult.getMessages().get(0);
}
#Override
public int getMessageCount(String queueUrl) {
GetQueueAttributesResult queueAttributes = sqsClient.getQueueAttributes(queueUrl, Arrays.asList("ApproximateNumberOfMessages"));
return Integer.valueOf(queueAttributes.getAttributes().get("ApproximateNumberOfMessages"));
}
and following are my test cases for these methods using mockito are failing with NPE.
#Test
public void testRecieveMessage() {
Message message = new Message();
message.setBody("Message Body");
List<Message> messages = new ArrayList<>();
messages.add(message);
ReceiveMessageResult result = new ReceiveMessageResult();
result.setMessages(messages);
when(mock(ReceiveMessageResult.class).getMessages()).thenReturn(messages);
when(mock(List.class).get(0)).thenReturn(message);
when(this.amazonSQSClient.receiveMessage(mock(ReceiveMessageRequest.class))).thenReturn(result);
this.amazonQueueService.recieveMessage(anyString());
verify(this.amazonSQSClient, times(1)).receiveMessage(mock(ReceiveMessageRequest.class));
//Assert.assertNotNull(msg);
}
java.lang.NullPointerException
at com.example.queue.service.impl.AmazonSQSService.recieveMessage(AmazonSQSService.java:46)
at com.example.AmazonSQSServiceTest.testRecieveMessage(AmazonSQSServiceTest.java:77)
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.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
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)
#Test
public void testMessageCount() {
GetQueueAttributesResult result = new GetQueueAttributesResult();
result.addAttributesEntry("ApproximateNumberOfMessages", "10");
List<String> attrs = Arrays.asList("ApproximateNumberOfMessages");
when(this.amazonSQSClient.getQueueAttributes(anyString(), eq(attrs))).thenReturn(result);
this.amazonQueueService.getMessageCount(anyString());
}
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
2 matchers expected, 1 recorded:
-> at com.example.AmazonSQSServiceTest.testMessageCount(AmazonSQSServiceTest.java:96)
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));
For more info see javadoc for Matchers class.
at com.example.queue.service.impl.AmazonSQSService.getMessageCount(AmazonSQSService.java:58)
at com.example.AmazonSQSServiceTest.testMessageCount(AmazonSQSServiceTest.java:96)
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.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
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)
Am I missing something?
Here is what your code does:
ReceiveMessageRequest request = new ReceiveMessageRequest().withQueueUrl(queueUrl).withMaxNumberOfMessages(1);
ReceiveMessageResult receiveMessageResult = this.sqsClient.receiveMessage(request);
So it creates a new request, and passes ths new request to sqsClient.receiveMessage().
Here's how you test that:
when(this.amazonSQSClient.receiveMessage(mock(ReceiveMessageRequest.class))).thenReturn(result);
So your test tells th mock client to return result when receiveMessage() is called with a mock ReceiveMessageRequest.
So that can't work. The mock ReceiveMessageRequest is not equal to the new request used in the code. You need to do something like
when(this.amazonSQSClient.receiveMessage(any(ReceiveMessageRequest.class))).thenReturn(result);
So that, whetever the request passed to receiveMessage, the mock client returns the result.
Regarding your second question:
this.amazonQueueService.getMessageCount(anyString());
doesn't make sense. You need to call your method with a real, given string.
I'm trying to write some tests using Mockito and I managed to write them for findAll and delete operations but for the create and update, they won't work.
#RunWith(MockitoJUnitRunner.class)
public class RentedControllerTest {
#Mock
private RentedService rentalService;
#Mock
private MovieService movieService;
#Mock
private ClientService clientService;
#InjectMocks
private RentedController rentalController;
#InjectMocks
private MovieController movieController;
#InjectMocks
private ClientController clientController;
#Before
public void setUp() throws Exception {
initMocks(this);
}
#Test
public void getMovies() throws Exception {
List<Movie> movies = new ArrayList<>();
movies.add(mock(Movie.class));
// System.out.println(movies.toString());
when(movieService.findAll()).thenReturn(movies);
//// System.out.println(movieService.findAll().toString());
MoviesDto response = movieController.getMovies();
assertEquals("should be 1 movie", 1, response.getMovies().size());
}
#Test
public void updateMovie() throws Exception {
Movie movie = new Movie(2,"Lotr",0, "dir2", 2003);
MovieDto movieDto = mock(MovieDto.class);
System.out.println(movie.toString());
when(movieService.updateMovie(anyInt(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(movie);
// Movie m = new Movie();
// m = movieService.updateMovie(2,"Lotrrrrr",0, "dir2", 2003);
// System.out.println(m.toString());
Map<String, MovieDto> map = movieController.updateMovie(2, movieDto);
System.out.println(map.toString());
assertEquals("Title should be Lots", "Lotr", map.get("movie").getName());
}
#Test
public void createMovie() throws Exception {
Movie movie = new Movie(2,"Lotr",0, "dir2", 2003);
MovieDto movieDto = mock(MovieDto.class);
when(movieService.createMovie(anyInt(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(movie);
Map<String, MovieDto> map = movieController.createMovie(movieDto);
assertEquals("Title should be Lotr", "Lotr", map.get("movie").getName());
}
#Test
public void deleteMovie() throws Exception {
ResponseEntity response = movieController.deleteMovie(1);
assertEquals("Http status should be OK", HttpStatus.OK, response.getStatusCode());
}
}
So the line "when(movieService.update....) work's just fine. I tested it with the write lines as you can see in the code and it works. The problem is here
Map<String, MovieDto> map = movieController.updateMovie(2, movieDto);
I gives me NullPointerException inside that method. The method looks like this:
#RequestMapping(value = "/movies/{movieId}", method = RequestMethod.PUT, consumes = CatalogMediaType.API_JSON)
public Map<String, MovieDto> updateMovie(#PathVariable final Integer movieId,
#RequestBody final MovieDto movieDto) {
log.trace("updateMovie: movieId={} movieDto={}", movieId, movieDto);
Movie movie = movieService.updateMovie(movieId, movieDto.getMovie().getName(), movieDto.getMovie().getNumberofrentals(), movieDto.getMovie().getDirector(), movieDto.getMovie().getYear());
Map<String, MovieDto> movieDtoMap = new HashMap<>();
movieDtoMap.put("movie", new MovieDto(movie));
log.trace("updateMovie: movieDtoMap={}", movieDtoMap);
return movieDtoMap;
}
The application itself works perfectly, the problem arises only when runing the mockito tests.
java.lang.NullPointerException
at ro.ubb.stcatalog.web.controller.MovieController.updateMovie(MovieController.java:41)
at ro.ubb.stcatalog.web.controller.RentedControllerTest.updateMovie(RentedControllerTest.java:82)
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:483)
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.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
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:119)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
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:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
2016-05-26T23:51:52,845 TRACE [main]: MovieController - createMovie: moviesDto=Mock for MovieDto, hashCode: 825249556
java.lang.NullPointerException
at ro.ubb.stcatalog.web.controller.MovieController.createMovie(MovieController.java:54)
at ro.ubb.stcatalog.web.controller.RentedControllerTest.createMovie(RentedControllerTest.java:92)
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:483)
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.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
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:119)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
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:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
I don't really understand what the problem is if the findAll and delete work just fine... Any ideas?
I believe the mocking of MovieDto class is causing the NPE, as your controller is expecting a few params to be present in the DTO, which are not being set by the mock(), such as movieDto.getMovie().getName().
Create a MovieDto object from scratch with all the required params, or set the params post mocking, and you should be fine.
The following should work.
#Test
public void updateMovie() throws Exception {
Movie movie = new Movie(2,"Lotr",0, "dir2", 2003);
MovieDto movieDto = mock(MovieDto.class);
// Added the following line
movieDto.setMovie(movie);
System.out.println(movie.toString());
when(movieService.updateMovie(anyInt(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(movie);
Map<String, MovieDto> map = movieController.updateMovie(2, movieDto);
System.out.println(map.toString());
assertEquals("Title should be Lots", "Lotr", map.get("movie").getName());
}
Looks like some dependency for the MovieController isn't getting set.
java.lang.NullPointerException
at ro.ubb.stcatalog.web.controller.MovieController.createMovie(MovieController.java:54)
You need to populate movieDto first. When you are doing get in the actual code its like you are doing get on a null which gives a NullPointer. And also Both values should be same. In when condition you are telling movieId as anyInt() and in the actual method call you are giving it as 2. That won't work. Both should be same as below.
when(movieService.updateMovie(**2**, anyString(), anyInt(), anyString(), anyInt())).thenReturn(movie);
Map<String, MovieDto> map = movieController.updateMovie(**2**, movieDto);