Java.lang.NullPointerException what's wrong - spring

It says error in this method a null pointer Exception
#Test
public void showBookListPage() throws Exception {
List<Book> expectedBookList = bookService.findAll();
BookService bookService = mock(BookService.class);
when( bookService.findAll()).thenReturn(expectedBookList);
BookController bookController = new BookController(bookService);
MockMvc mockMvc = standaloneSetup(bookController).build();
mockMvc.perform(get(" /book/bookList"))
.andExpect(view().name("bookList"))
.andExpect(model().attributeExists("bookList"))
.andExpect(model().attribute("bookList", hasItems(expectedBookList.toArray())));
}
}
Other than that everything seems to be correct
This is the error I got after mocking the book service first before call
java.lang.IllegalStateException: missing behavior definition for the preceding method call:
BookService.findAll()
Usage is: expect(a.foo()).andXXX()
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:42)
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:94)
at com.sun.proxy.$Proxy134.findAll(Unknown Source)
at com.admintest.controller.BookControllerTest.showBookListPage(BookControllerTest.java:101)
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.springf
And this is my edit to the test method
#Test
public void showBookListPage() throws Exception {
BookService bookService = mock(BookService.class);
List<Book> expectedBookList = bookService.findAll();
when(bookService.findAll()).thenReturn(expectedBookList);
BookController bookController = new BookController(bookService);
MockMvc mockMvc = standaloneSetup(bookController).build();
mockMvc.perform(get(" /book/bookList"))
.andExpect(view().name("bookList"))
.andExpect(model().attributeExists("bookList"))
.andExpect(model().attribute("bookList", hasItems(expectedBookList.toArray())));
}
And by the way this is the controller
#RequestMapping("/bookList")
public String bookList(Model model) {
List<Book> bookList = bookService.findAll();
model.addAttribute("bookList", bookList);
return "bookList";
}

You have to mock the bookService before using it. Not after it's usage. So do the mocking of bookService in #BeforeMethod

Related

Testing Spring Controller with Mockito

I am trying to learn to test using Spring 5, Mockito, and JUnit 5.
I have a small normal controller class and its test is as below:
#Controller
#RequestMapping("/customer")
public class CustomerController {
#Autowired
CustomerService customerService;
#Autowired
CustomerForm customerForm;
#GetMapping("/index")
public ModelAndView index(){
String customerName = customerService.getCustomerById(14).getFirstname(); <-- Giving me error here
customerForm.setCustomerName(customerName);
ModelAndView modelAndView = new ModelAndView("customer/pages/customer/Home");
modelAndView.addObject("customerForm", customerForm);
return modelAndView;
}
}
#ExtendWith(MockitoExtension.class)
class CustomerControllerTest {
#InjectMocks
CustomerController customerController;
#Mock
CustomerServiceImpl customerService;
#Mock
CustomerForm customerForm;
Customer customer;
String customerName;
#SuppressWarnings("deprecation")
#BeforeEach
void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
customer = new Customer(14, "John");
customerName = "John";
}
#Test
void testIndex() {
int customerId = 14;
when(customerService.getCustomerById(customerId).getFirstname()).thenReturn(customerName); <-- Giving me error here, NullPointerException
customerForm.setCustomerName(customerName);
ModelAndView mav = customerController.index();
assertEquals( customerForm, mav.getModel().get("customerForm"));
}
}
Error:
java.lang.NullPointerException
at com.primis.controller.CustomerControllerTest.testIndex(CustomerControllerTest.java:66)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
When I run this test, I am getting NullPointerException as shown.
Please can someone point me in the right direction, what I am doing wrong.
Thank you
You have to mock customerService.getCustomerById(customerId) first, otherwise it will return null and, in this case, throw NPE.
You are mocking the wrong thing:
when(customerService.getCustomerById(customerId).getFirstname()).thenReturn(customerName);
What you actually need to mock is only the call customerService.getCustomerById(). This means that your testing code should be something like:
#ExtendWith(MockitoExtension.class)
class CustomerControllerTest {
#InjectMocks
CustomerController customerController;
#Mock
CustomerServiceImpl customerService;
#Mock
CustomerForm customerForm;
Customer customer;
String customerName;
#SuppressWarnings("deprecation")
#BeforeEach
void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
customer = new Customer(14, "John");
customerName = "John";
}
#Test
void testIndex() {
int customerId = 14;
when(customerService.getCustomerById(customerId)).thenReturn(customer);
customerForm.setCustomerName(customerName);
ModelAndView mav = customerController.index();
assertEquals( customerForm, mav.getModel().get("customerForm"));
}
}
As a side note, I believe that with #ExtendWith(MockitoExtension.class) you don't really need the explicit MockitoAnnotations.initMocks(this); call.

MockMvc peform is return nullPointerException in integration tests

I'm trying to run integration tests for my Spring project, it's a simple get method that returns a String output from the DB for the id given. But I keep getting a NullPointerException on the Mockmvc in the MockMvc.perform within my tests.
Here is the test:
#WebMvcTest(OutputController.class)
public class OutputControllerTests {
#Autowired
private MockMvc mockMvc;
#MockBea
OutputService outputService;
#Test
public void returnOutputForValidId() throws Exception {
OutputService service = Mockito.mock(OutputService.class);
when(service.findOutputById("TEST")).thenReturn("Test output");
String getOutputMapping = "/output/{systemID}";
String id = "TEST";
mockMvc.perform(get(getOuputMapping, id))
.andDo(print()).andExpect(status().isOk())
.andExpect(content().string("Test output"));
}
Here is the controller - OutputController:
#RestController
public class OutputController {
private final OutputService outputService;
public OutputController(OutputService outputService) {
this.outputService = outputService;
}
#GetMapping("/output/{id}")
#CrossOrigin
public String getOutputByID(#PathVariable String Id) {
String output = outputService.findOutputById(Id);
return output;
}
}
The full error is :
java.lang.NullPointerException
at .com.output.OutputControllerTests.returnOutputForValidId(OutputControllerTests.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
You don't need to autowire MockMvc object. Try with this instead:
import org.junit.jupiter.api.BeforeEach;
//...
private MockMvc mockMvc;
//...
#BeforeEach
public void setUp(WebApplicationContext context) {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}

Null after #InjectMocks in Mockito Junit

I am having some troubles passing a dependancy while unit testing with JUnit.
Consider these pieces of code:
This is the dependacy injecton into the class which i want to test, lets call it Service.
error log trace
java.lang.NullPointerException
at com.example.demo.service.ServiceClass.getCustomerById(ServiceClass.java:50)
at com.example.demo.service.ServiceClassTest.getCustomerByIdTest(ServiceClassTest.java:46)
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.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
ServiceClass
#Service
public class ServiceClass {
public static final String CRM_JPA_URI = "http://localhost:9000/api/tickets/";
#Autowired
RestTemplate restTemplate;
public Customer getCustomerById(int customerId) {
ResponseEntity<Customer> entity = restTemplate.getForEntity(CRM_JPA_URI +"ticket/{customerId}",
Customer.class, customerId);
return entity.getBody();
}
}
ServiceClassTest
#RunWith(MockitoJUnitRunner.class)
public class ServiceClassTest {
#Mock
RestTemplate mockRestTemplate;
#InjectMocks
ServiceClass serviceClass;
/**
* getCustomerByIdTest
*/
#Test
public void getCustomerByIdTest(){
Customer customer = new Customer();
customer.setPassengerName("Ramesh");
customer.setBookingDate("09/09/2019");
customer.setDestStation("pamur");
customer.setEmail("r#gmail.com");
customer.setSourceStation("ongole");
Mockito.lenient().when(mockRestTemplate.getForEntity("http://localhost:9000/api/tickets/ticket/1", Customer.class)).
thenReturn(new ResponseEntity<Customer>(customer,HttpStatus.OK));
System.out.println("object is--->"+serviceClass.getCustomerById(1));
assertEquals(customer, serviceClass.getCustomerById(1));
}
}
Try calling
MockitoAnnotations.initMocks(this);
in your test method or #Before setup() method

Introducing Spring Batch fails Dao-Test

I am using Spring Batch in a Spring Boot application as below. Spring Batch and the application seem to work fine with that configuration.
However, with that configuration for a simple Dao-Test (not for Spring Batch) I get the following exception. Without the Spring Batch configuration the test is running fine. Update: The problem appears if I configure to use an own JobRepository with a transaction manager (below in class MyBatchConfigurer).
I tried to provide another transaction manager for Spring Batch but I am running from exception to exception.
org.springframework.dao.InvalidDataAccessApiUsageException: no transaction is in progress; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress
Caused by: javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.internal.SessionImpl.checkTransactionNeeded(SessionImpl.java:3505)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1427)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1423)
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.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:350)
at com.sun.proxy.$Proxy165.flush(Unknown Source)
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.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:305)
at com.sun.proxy.$Proxy165.flush(Unknown Source)
at com.foo.dao.GenericDao.save(GenericDao.java:60)
at com.foo.dao.GenericDao$$FastClassBySpringCGLIB$$71a0996b.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
... 37 more
Test Setup
#SpringBootTest
#RunWith(SpringRunner.class)
#EntityScan(basePackages = "com.foo.entity")
#DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
#TestPropertySource("/mytest.properties")
#Sql(executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, scripts = "classpath:/testdata.sql")
public class MyTest {
#Inject
private OrderDao sut;
#Test
public void test_findByAnotherFieldId() {
final Order order = // build an order ...
sut.save(order);
final Order result = sut.findByAnotherFieldId("valueOfOtherField");
assertThat(result).isEqualTo(order);
}
}
Spring Batch Job configuration
#Configuration
#EnableBatchProcessing
#Import(OracleDatabaseConfig.class)
#ComponentScan(basePackageClasses = MyBatchConfigurer.class)
public class BatchJobConfig {
// Injects...
#Qualifier("analyseOrdersJob")
#Bean
public Job analyseOrdersJob() {
return jobBuilderFactory.get("analyseOrdersJob").start(analyseOrdersStep()).build();
}
#Bean
public Step analyseOrdersStep() {
return stepBuilderFactory.get("analyseOrdersStep").<Order, String>chunk(4)
.reader(orderItemReader) //
.processor(orderItemProcessor) //
.writer(orderItemWriter) //
.build();
}
}
Spring Batch configuration
#Component
public class MyBatchConfigurer extends DefaultBatchConfigurer {
#Inject
private DataSource dataSource;
#Override
public JobRepository getJobRepository() {
try {
return extractJobRepository();
} catch (final Exception e) {
throw new BatchConfigurationException(e);
}
}
private JobRepository extractJobRepository() throws Exception {
final JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSource);
factory.setTransactionManager(getTransactionManager());
factory.afterPropertiesSet();
return factory.getObject();
}
}
ItemReader
#Component
#StepScope
public class OrderItemReader implements ItemReader<Order> {
#Inject
private OrderDao orderdao;
private int nextOrderIndex;
private List<Order> orders;
#PostConstruct
public void postConstruct() {
orders = orderdao.findAll();
}
#Override
public Order read() {
if (nextOrderIndex < orders.size()) {
final Order order = orders.get(nextOrderIndex);
nextOrderIndex++;
return order;
}
return null;
}
}
ItemWriter and ItemProcessor are similarly configured.

NullPointerException in the BeforeClass (spring boot)

I want to make an insert in my DB before all tests just once. That's what I'm trying to do in the setUp() method. But got nullpointer. Spring boot version is 1.5.1.RELEASE. Any ideas?
This is from my test class:
#Autowired
private static UserRepository userRepository;
#BeforeClass
public static void setUp() {
User user = User.
.builder()
.id(10)
.name("John")
.build();
userRepository.deleteAll(); //NullPointerException at this step
userRepository.save(user);
}
This is my entity class:
#Entity
#Table(schema="test", name = "TBL_USERS")
#AllArgsConstructor
#Builder
#Data public class User implements Persistable<String>{
#Id
#Column(name = "ID", columnDefinition = "decimal")
private String id;
#Column(name = "NAME", columnDefinition = "char", nullable = false)
private String name;
...
}
This is the interface:
public interface UserRepository extends JpaRepository<User, String> {}
The stack trace:
java.lang.NullPointerException
at com.company.myapp.get.GetUserTest.setUp(GetUserTest.java:58)
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.RunBefores.evaluate(RunBefores.java:24)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
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 com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Short answer: You can not inject static UserRepository (#Autowired)
Please read here Reason we could not inject static field
It doesn't look like you initialized userRepository to anything in your beforeClass method before calling deleteAll() on it. That's why you got your NPE.
Is your test class annotated with #RunWith(SpringRunner.class)?
You need to do something like this..
#RunWith(SpringRunner.class)
#SpringBootTest
public class XXXTest {
#Autowired
private UserRepository userRepository;
#Before
public void setUp() {
......
}

Resources