I am trying to write test case for following controller code using JUnit and mockito. But I am getting null pointer Exception. I am new to JUnit testing. can any one please tell what I am doing wrong here?
DepartmentController
#RestController
#RequestMapping("/api.spacestudy.com/SpaceStudy")
public class DepartmentController {
#Autowired
DepartmentService depService;
#CrossOrigin(origins = "http://localhost:4200")
#GetMapping("/LoadDept")
public Department findDeptId() {
return depService.findDeptId();
}
}
DepaermentControllerTest
#WebMvcTest
public class DepartmentControllerTest {
#Autowired
private MockMvc mockMvc;
#Mock
public DepartmentService depService;
#InjectMocks
DepartmentController departmentController;
#Before
public void setup() throws Exception {
mockMvc = MockMvcBuilders.standaloneSetup(departmentController).build();
}
#Test
public void findDeptIdTest() throws Exception
{
Department department = new Department();
department.setnDeptId(10);
Mockito.when(depService.findDeptId()).thenReturn(department);
mockMvc.perform(get("/api.spacestudy.com/SpaceStudy/LoadDept").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.nDeptId", Matchers.is(10)));
}
}
Test Result
java.lang.NullPointerException
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.detectHandlerMethods(AbstractHandlerMethodMapping.java:227)
at org.springframework.test.web.servlet.setup.StandaloneMockMvcBuilder$StaticRequestMappingHandlerMapping.registerHandlers(StandaloneMockMvcBuilder.java:490)
at org.springframework.test.web.servlet.setup.StandaloneMockMvcBuilder.registerMvcSingletons(StandaloneMockMvcBuilder.java:356)
at org.springframework.test.web.servlet.setup.StandaloneMockMvcBuilder.initWebAppContext(StandaloneMockMvcBuilder.java:341)
at org.springframework.test.web.servlet.setup.AbstractMockMvcBuilder.build(AbstractMockMvcBuilder.java:139)
at com.spacestudy.DepartmentControllerTest.setup(DepartmentControllerTest.java:38)
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.RunBefores.evaluate(RunBefores.java:24)
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.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)
to solve that problem, you have to give an instance of DepartmentController class at standaloneSetup(). I had the same issue while working on some unit testing and after that, my problem disappeared. Try to do it:
#Before
public void setup() throws Exception {
mockMvc = MockMvcBuilders.standaloneSetup(new DepartmentController()).build();
}
Related
I am doing a simple caching in my springboot application. Here I am trying to perform findall,delete and update operations with JPA. At the same time I am trying to update my cache also after performing each operations.
This is my entity
#Entity
#Table(name = "cars")
public class Cars implements Serializable{
#Id
#Column(name = "carId")
private long carId;
#Column(name = "name")
private String name;
..........getters and setters.......
This is my service
#Service
public class CarServiceImpl implements CarService{
#Autowired
private CarRepository carRepo;
#Override
#Transactional
#Cacheable(value = "cars")
public Cars save(Cars car) {
// TODO Auto-generated method stub
System.out.println("reciving from DB for save");
return carRepo.save(car);
}
#Override
#Transactional
#CacheEvict(value="cars" ,key="#id")
public void delete(long id) {
System.out.println("reciving from DB for delete");
// TODO Auto-generated method stub
carRepo.deleteById(id);
}
#Override
#Transactional
#CachePut(value="cars",key="#id")
public Cars update(Cars car,long id) {
System.out.println("reciving from DB for update");
// TODO Auto-generated method stub
return carRepo.save(car);
}
#Override
#Transactional
#Cacheable(value="cars",key="#id")
public List<Cars> getAll(long id) {
System.out.println("reciving from DB for show");
// TODO Auto-generated method stub
return carRepo.findAll();
}
this is the error I am getting when I perform update operation to add a new entity and then call getAll method where it loads from cache .
java.lang.ClassCastException: com.example.springCaching.entity.Cars cannot be cast to java.util.List
at com.example.springCaching.serviceImpl.CarServiceImpl$$EnhancerBySpringCGLIB$$80d45199.getAll(<generated>) ~[classes/:na]
at com.example.springCaching.contoller.CarController.show(CarController.java:39) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_161]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_161]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_161]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_161]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) ~[spring-webmvc-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:893) ~[spring-webmvc-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:798) ~[spring-webmvc-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.web.se
For a test class with a private void method, what is the right way to mock the behaviour of the method. The solution below invokes the method instead.
public class TestWizard {
private void testOne(){
throw new NullPointerException();
}
private void testTwo(){
testOne();
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest({TestWizard.class})
public class WTest {
#Test
public void testWizard() throws Exception {
TestWizard wizard2 = Whitebox.newInstance(TestWizard.class);
TestWizard wizard = Mockito.spy(wizard2);
PowerMockito.doNothing().when(wizard, "testTwo");
}
}
The error is:
java.lang.NullPointerException
at tuk.pos.wizard.model.TestWizard.testOne(TestWizard.java:6)
at tuk.pos.wizard.model.TestWizard.testTwo(TestWizard.java:10)
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.powermock.reflect.internal.WhiteboxImpl.performMethodInvocation(WhiteboxImpl.java:1862)
at org.powermock.reflect.internal.WhiteboxImpl.doInvokeMethod(WhiteboxImpl.java:824)
at org.powermock.reflect.internal.WhiteboxImpl.invokeMethod(WhiteboxImpl.java:689)
at org.powermock.reflect.Whitebox.invokeMethod(Whitebox.java:401)
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:105)
Use PowerMockito.spy(...) instead of Mockito.spy(...).
Tested with PowerMockito 2.0.5
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
#RunWith(PowerMockRunner.class)
#PrepareForTest(WTest.TestWizard.class)
public class WTest {
public class TestWizard {
private void testOne(){
throw new NullPointerException();
}
private void testTwo(){
testOne();
}
}
#Test
public void testWizard() throws Exception {
TestWizard spy = PowerMockito.spy(Whitebox.newInstance(TestWizard.class));
PowerMockito.doNothing().when(spy, "testTwo");
spy.testTwo();
}
}
Try to restrict the usage of spies to legacy code. In most other cases a refactoring should be the preferred solution.
I am trying Mockito for mocking and unit testing.
Trying to mock an autowired bean using #MockBean. But the bean is null at run time.
Class under test.
#Service
public class UserServiceImpl {
#Autowired
GenericRestClient restClient;
#Autowired
RequestMapper requestMapper;
#Autowired
ResponseMapper responseMapper;
#Override
public List<User> findUsers(RRequest requestBody,
String index) throws HostException {
List<User> users=
requestMapper.mapRequest("test");
// ...doing something
return users;
}
The test class :
import static org.junit.Assert.assertNotNull;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.boot.test.mock.mockito.MockBean;
#RunWith(MockitoJUnitRunner.class)
public class UserServiceImplTest {
#MockBean
GenericRestClient restClient;
#MockBean
RequestMapper requestMapper;
#MockBean
ResponseMapper responseMapper;
#InjectMocks
UserServiceImpl userService;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testFindUsers() {
List<Users> users = null;
Mockito.when(requestMapper.mapRequest("test"))
.thenReturn(users);
assertNull(users);
}
}
Error :
java.lang.NullPointerException
at test.my.code.UserServiceImplTest.testFindUsers(UserServiceImplTest.java:10)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java: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.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)
I have debugged, NullPointerException is because of requestMapper (mocked using MockBean as it is null.)
What is wrong with this code?
Unlike #abinmichael I don't suggest using Spring Runner to run this test. Your test is a unit test, and running Spring (creating an application context) is a very expensive operation, more suitable for integration testing.
I'm not a mockito expert, but I believe, you should refactor slightly the UserServiceImpl so that the dependencies will become visible:
#Service
public class UserServiceImpl {
private final GenericRestClient restClient;
private final RequestMapper requestMapper;
private final ResponseMapper responseMapper;
#Autowired // in recent spring version, this annotation can be omitted
public UserServiceImpl(GenericRestClient restClient, RequestMapper requestMapper, ResponseMapper responseMapper) {
this.restClient = restClient;
this.requestMapper = requestMapper;
this.responseMapper = responseMapper;
}
...
With such an approach there is no need in #InjectMocks anymore:
#RunWith(MockitoJUnitRunner.class)
public class UserServiceImplTest {
#Mock
GenericRestClient restClient;
#Mock
RequestMapper requestMapper;
#Mock
ResponseMapper responseMapper;
UserServiceImpl userService;
#Before
public void init() {
userService = new UserServiceImpl(restClient, requestMapper, responseMapper);
}
....
}
If you insist on using fields injection, read The accepted answer to get more information about how does #InjectMocks work. Maybe you don't have "private" access modifier, maybe you have some mix between Constructor injection and field injection and #InjectMocks doesn't not support both simultaneously
I suggest you can try this approach, using #InjectMocks for the test target and use #Mock for injected classes inside that service.
No need to use #Before since you used field injection.
#RunWith(SpringRunner.class)
#SpringBootTest(classes = YourMainClass.class)
public class UserServiceImplTest {
#Mock
GenericRestClient restClient;
#Mock
RequestMapper requestMapper;
#Mock
ResponseMapper responseMapper;
#InjectMocks
UserServiceImpl userService
#Test
public void testFindUsers() {
}
}
Can you try running the test after changing to
#RunWith(SpringRunner.class)
#SpringBootTest
public class UserServiceImplTest {
The javadoc https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/mock/mockito/MockBean.html
states
#Target(value={TYPE,FIELD})
#Retention(value=RUNTIME)
#Documented
#Repeatable(value=MockBeans.class)
public #interface MockBean
Annotation that can be used to add mocks to a Spring ApplicationContext. Can be used as a class level annotation or on fields in either #Configuration classes, or test classes that are #RunWith the SpringRunner.
I'm trying to test my controller that has a handler with a RequestParam configured with a default value pointed to a placeholder:
#Controller
public class AgeController {
#GetMapping("/age")
public String home(#RequestParam(name="current", defaultValue="${default.age}") Integer age) {
return "age"+age;
}
}
This works fine when I'm testing through my browser but when I use the following test case, it throws an exception:
Test Case:
public class AgeControllerTest {
AgeController controller
MockMvc mockMvc;
#Before
public void setUp() {
ageController = new AgeController();
mockMvc = MockMvcBuilders.standaloneSetup(controller).addPlaceholderValue("default.age", "10").build();
}
#Test
public void test() {
mockMvc.perform(get("/age")).andExpect(status().isOk());
}
}
Exception:
Caused by: java.lang.NumberFormatException: For input string: "${default.age}"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.valueOf(Unknown Source)
at org.springframework.util.NumberUtils.parseNumber(NumberUtils.java:208)
at org.springframework.beans.propertyeditors.CustomNumberEditor.setAsText(CustomNumberEditor.java:113)
at org.springframework.beans.TypeConverterDelegate.doConvertTextValue(TypeConverterDelegate.java:468)
at org.springframework.beans.TypeConverterDelegate.doConvertValue(TypeConverterDelegate.java:441)
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:199)
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:108)
at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:64)
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:47)
at org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java:713)
at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:120)
Consider using #TestPropertySource.
#TestPropertySource(properties = {"default.age = 10"})
public class AgeControllerTest {
...
}
Trying to use jmockit to stub out a javax.sql.DataSource class. Any ideas?
public class MyTest
{
#MockClass(realClass = DataSource.class)
public static class MockDataSource {
}
#Before
public void setup()
{
Mockit.setUpMocks(MockDataSource.class);
}
#Test
public void testCreateGetUpdateUser()
{
new NonStrictExpectations()
{
...
};
...
}
}
I run the test in eclipse and get this
java.lang.IllegalArgumentException: Not a modifiable class: javax.sql.DataSource
at mockit.internal.RedefinitionEngine.createClassReaderForRealClass(RedefinitionEngine.java:222)
at mockit.internal.RedefinitionEngine.modifyRealClass(RedefinitionEngine.java:207)
at mockit.internal.RedefinitionEngine.redefineMethods(RedefinitionEngine.java:199)
at mockit.internal.RedefinitionEngine.redefineMethods(RedefinitionEngine.java:193)
at mockit.Mockit.setUpMocks(Mockit.java:274)
at MyTest.setup(EntityManagerUTest.java:77)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.internal.runners.MethodRoadie.runBefores(MethodRoadie.java:122)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:86)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
I am not a user of jmockit (I prefer http://mockito.org/ which seems simpler to use), but I think that your #MockClass is not complete - mabybe you need a #Mock method in it:
http://jmockit.googlecode.com/svn/trunk/www/tutorial/StateBasedTesting.html#interfaces