#Service
public class MyClass {
...
#Autowired
public MyClass(#Value("${my.value}") String myValue) {
...
}
...
}
My Test class:
public class MyTest {
#Mock(name = "solrServer")
private SolrServer solrServer;
#InjectMocks
private MyClass myClassMock;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
....
}
I have an exeption as follow:
org.mockito.exceptions.base.MockitoException: Cannot instantiate
#InjectMocks field named 'myClassMock' of type 'class
mypackage.MyClass'. You haven't provided the
instance at field declaration so I tried to construct the instance.
However the constructor or the initialization block threw an exception
: null
at mypackage.MyTest.setUp(MyTest.java:46)
...
Caused by: java.lang.NullPointerException
...
How to inject #Value field from MyTest class, and fixed it?
You can do it within the #Before annotated method by making an instance of your class manually, like so:
public class MyTest {
#Mock(name = "solrServer")
private SolrServer solrServer;
#InjectMocks
private MyClass myClassMock;
#Before
public void setUp() {
myClassMock = new MyClass("value you need");
MockitoAnnotations.initMocks(this);
}
#Test
....
}
Related
I have a class that autowires another #ConfigurationProperties class.
#Configuration
#Data
#ConfigurationProperties("api")
public class ApiConfiguration {
private String myUrl;
}
....
Class that autowires above class ApiConfiguration
public class Services implements anotherServices {
#Autowired
private ApiConfiguration apiConfiguration;
....
#Override
public Mono<SomeClass> getClassInfo(String ..., String ...) {
return someWebClient
.get()
.uri(apiConfiguration.getRewardsBalance()) ---> **Null pointer**
Now when I autowire ApiConfiguration class, if I System.out the output I see that it's been set with whatever String I passed in, meaning My junit class is autowiring apiConfiguration class however, the actual implementation class throws a null pointer exception on apiConfiguration.
Test class
#ExtendWith(SpringExtension.class)
#ActiveProfiles("test")
#EnableConfigurationProperties(value = {ApplicationConfiguration.class,ApiConfiguration.class})
#TestPropertySource("classpath:application.properties")
#ContextConfiguration(
initializers = ApplicationContextInitializer.class)
class AccountDetailsServicesTest {
#Autowired
private ApiConfiguration apiConfiguration;
#BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
...
apiConfiguration.setApi("http://localhost:8080");
...
I have service:
#Service
class UserService {
private final Map<AbstractSomeService, CustomEnum> someMap;
public UserService(List<AbstractSomeService> someService) {
someService.forEach(service -> someMap.put(service.getCustomEnum(), service));
}
public void logicExecution() {
//code
}
}
When i am mocking as below: i am getting NullPointer:
#Mock
private SomeService someService; // Service which is extended of AbstractSomeService
#InjectMocks
private UserService userService = new UserService(Collection.singletonList(someService))
#BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
}
#Test
public void testBrokenJunit() {
userService.logicExecution(); // NULL POINTER HERE (
}
SomeService:
#Service
public class SomeService extends AbstactSomeService() {
public CustomEnum getCustomEnum() {
return CustomEnum.BROKEN_JUNIT_TEST;
}
//logic here
}
Stack trace is quite simple:
java.lang.NullPointerException: Cannot invoke "getCustomEnum()" because "service" is null
StackTrace without constructor initialization:
org.mockito.exceptions.misusing.InjectMocksException:
Cannot instantiate #InjectMocks field named 'UserService' of type '...'.
You haven't provided the instance at field declaration so I tried to construct the instance.
However the constructor or the initialization block threw an exception : Cannot invoke "java.util.List.forEach(java.util.function.Consumer)" because "someService" is null
at
Caused by: java.lang.NullPointerException: Cannot invoke "java.util.List.forEach(java.util.function.Consumer)" because "someService" is null
at UserService.<init>
P.S.
When i am using real object of UserService, not a mock everything is ok.
But it doesn't work with #InjectMocks
Try the following in your test class (you don't need to initialize UserService with a new instance via the constructor, #InjectMocks will do that for you):
#Mock
private SomeService someService;
#InjectMocks
private UserService userService;
#BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
}
#Test
public void testBrokenJunit() {
userService.logicExecution();
}
If this does not work because you have a List and not a simple SomeService you can do the following:
#Mock
private SomeService someService;
private UserService userService;
#BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
userService = new UserService(Collection.singletonList(someService));
}
#Test
public void testBrokenJunit() {
userService.logicExecution();
}
Use #MockBean to create mock objects
import org.springframework.boot.test.mock.mockito.MockBean;
#MockBean
private User user;
I have a class name ServiceLocator
public class ServiceLocator implements ApplicationContextAware {
private transient ApplicationContext _applicationContext;
private static ServiceLocator _instance = new ServiceLocator();
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
_instance._applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return _instance._applicationContext;
}
public static Object findService(String serviceName) {
return _instance._applicationContext.getBean(serviceName);
}
}
I am trying to use that class to find Service into Approver class methods
public class ApproverService extends AbstractDataService implements IApproverService {
public void updateCompletedInboxStatus(String status) {
IInboxService inboxService = (IInboxService)ServiceLocator.findService("inboxService");
InboxItem inboxItem = inboxService.getInboxItem("test");
inboxItem.setWorkItemStatus(status);
inboxService.saveInboxItem(inboxItem);
}
}
With that code i am trying to write Junit with PowerMockRunner
#RunWith(PowerMockRunner.class)
#PrepareForTest({ApproverService.class})
public class ApproverServiceTest {
#InjectMocks
ApproverService approverService;
#Mock
IInboxService inboxService;
#Mock
ServiceLocator serviceLocator;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void updateCompletedInboxStatus() {
RequestAccessHeader reqHdr = new RequestAccessHeader();
reqHdr.setRequestStatus(AccessConstants.REQ_STATUS_HOLD_INT);
String status = "test";
PowerMockito.mockStatic(ServiceLocator.class);
when(serviceLocator.findService("inboxService")).thenReturn(inboxService);
approverService.updateCompletedInboxStatus(status);
}
}
But I am getting null pointer
java.lang.NullPointerException
at com.alnt.fabric.common.ServiceLocator.findService(ServiceLocator.java:25)
at com.alnt.access.approver.service.ApproverServiceTest.updateCompletedInboxStatus(ApproverServiceTest.java:80)
Please help me to find the solution for that issue.
The static method is obviously not mocked.
The problem is most probably because you haven't add the to-be-mocked class in #PrepareForTest
Change it to #PrepareForTest({ApproverService.class, ServiceLocator.class})
Off-topics:
Although it compiles, calling static method by instance reference is not a good practice. Therefore the line should be when(ServiceLocator.findService(...)).thenReturn(inboxService).
Another problem is, you tried to use Singleton pattern but in wrong way. A singleton is suppose to return you an instance so the caller can call its instance method. Your findService is preferably an instance method and to be called as ServiceLocator.getInstance().findService(...). To further improve, unless you really need it to be a singleton, you should make it a normal object instance and inject to objects that need it (given you are already using Spring, I see no reason making a Singleton)
The setup for the static method is not mocked correctly
#RunWith(PowerMockRunner.class)
#PrepareForTest({ServiceLocator.class}) //Prepare static class for mock
public class ApproverServiceTest {
#Mock
IInboxService inboxService;
#Mock
InboxItem item;
#InjectMocks
ApproverService approverService;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void updateCompletedInboxStatus() {
//Arrange
String status = "test";
PowerMockito.mockStatic(ServiceLocator.class);
when(ServiceLocator.findService("inboxService")) //<-- NOTE static call
.thenReturn(inboxService);
when(inboxService.getInboxItem("test")).thenReturn(item);
//Act
approverService.updateCompletedInboxStatus(status);
//...
}
}
Reference Mocking Static Method
The subject under test should actually be refactored to avoid the service locator anit-pattern / code smell and should follow explicit dependency principle via constructor injection.
public class ApproverService extends AbstractDataService implements IApproverService {
private IInboxService inboxService;
#Autowired
public ApproverService(IInboxService inboxService){
this.inboxService = inboxService;
}
public void updateCompletedInboxStatus(String status) {
InboxItem inboxItem = inboxService.getInboxItem("test");
inboxItem.setWorkItemStatus(status);
inboxService.saveInboxItem(inboxItem);
}
}
That way the subject class is genuine about what it needs to perform its function correctly,
And the test can then be refactored accordingly
#RunWith(PowerMockRunner.class)
public class ApproverServiceTest {
#Mock
IInboxService inboxService;
#Mock
InboxItem item;
#InjectMocks
ApproverService approverService;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void updateCompletedInboxStatus() {
//Arrange
String status = "test";
when(inboxService.getInboxItem("test")).thenReturn(item);
//Act
approverService.updateCompletedInboxStatus(status);
//...
}
}
I have a test class which is testing an other class method
Other class is structured like this
#Component
public abstract class ParentOpManager{
#Autowired
private ProcessorRequestWrapper processorRequestWrapper;
#Autowired
private XYProcessor xyProcessor;
}
#Component("childManager")
public class ChildOperationManager extends ParentOpManager{
}
public abstract class ParentClass{
protected final RequestWrapper requestWrapper;
protected final ParentOpManager parentOpManager;
public ParentClass(final RequestWrapper requestWrapper, final ParentOpManager parentOpManager){
this.requestWrapper = requestWrapper;
this.parentOpManager = parentOpManager;
}
}
further I have, child classes extending this class
public class ChildClass extends ParentClass{
#Autowired
private NinjaManager ninjaManager;
#Autowired
public ChildClass(final RequestWrapper requestWrapper, #Qualifier("childManager")final ParentOpManager parentOpManager){
super(requestWrapper, parentOpManager);
}
public void methodA() throws Exception {
Request item = requestWrapper.findItem(); // Problem place 1
}
public void methodB() throws Exception {
Request item = ninjaManager.findItem(); // Problem place 2
}
}
I need to test methods of ChildClass. For this I have written a test class.
//#RunWith(MockitoJunitRunner.class)
//#ContextConfiguration
public class TestClass{
#Mock
ChildOperationManager chOpManager;
#Mock
RequestWrapper requestWrapper;
#InjectMocks
ChildClass childObject;
#Before
public void setup(){
MockitoAnnotations.initMocks(this);
}
#Test
public void testSomeMethodA() throws Exception{
childObject.methodA();
}
}
So, the problem is when I am class methodA from test class, requestWrapper is NULL. I can not understand why this is happening ?
EDIT:
If i do like
#Mock
ChildOperationManager chOpManager = new ChildOperationManager();
#Mock
RequestWrapper requestWrapper;
#InjectMocks
ChildClass childObject = new childObject(requestWrapper, chOpManager);
Problem seams to be resolved. There is some other problem which might be some permission issue. But do you think doing this way is good approach ?
Your error is this:
#Autowired
public ChildClass(final RequestWrapper requestWrapper, #Qualifier("childManager")final ParentOpManager parentOpManager){
super(requestWrapper, parentOpManager);
}
public void methodA() throws Exception {
Request item = requestWrapper.findItem(); // this requestWrapper is null
}
You don't assign the requestWrapper reference in the child. So it remains null.
You should just remove the member variable requestWrapper and parentOpManager from the child. this way, you'll use the parent's one, which is initialized.
Problem is that Mockito tried to inject mock via constructor in first step.
public class DefaultInjectionEngine {
public void injectMocksOnFields(Set<Field> needingInjection, Set<Object> mocks, Object testClassInstance) {
MockInjection.onFields(needingInjection, testClassInstance)
.withMocks(mocks)
.tryConstructorInjection() <-- Here
.tryPropertyOrFieldInjection()
.handleSpyAnnotation()
.apply();
}
}
And if it found proper constructor, it doesn't try to inject mocks via property or field.
In your case you have constructor for ChildClass, which was picked by Mockito, but you don't initialize a fields in ChildClass.
As workaround, you can resolve it in this way (just don't use mockito injections):
RequestWrapper wrapper;
ChildOperationManager childOperationManager;
ChildClass childObject;
#Before
public void setUp() {
wrapper = Mockito.mock(RequestWrapper.class);
childOperationManager = Mockito.mock(ChildOperationManager.class);
childObject = new ChildClass(wrapper, childOperationManager );
}
I would like to set some common expectations on my timeServiceMock, but it is still null in before method. Any way to make it work without need to call before() in every test?
#RunWith(EasyMockRunner.class)
public class MyTest extends EasyMockSupport {
...#TestSubject and so on
#Mock
private TimeService timeServiceMock;
#Before
public void before() {
System.out.println(this.timeServiceMock);
}
...tests
}
Am I missing something?
It looks like EasyMockRunner only creates and injects mocks in #Test.
so if you want to use it in a #Before, remove the #Mock annotation from TimeService and create the mock yourself in #Before. Then you will have to inject the mock yourself into the #TestSubject.
So something like this:
#RunWith(EasyMockRunner.class)
public class MyTest extends EasyMockSupport {
#TestSubject and so on
Foo testSubject = ...
private TimeService timeServiceMock;
#Before
public void before() {
this.timeServiceMock = createMock(TimeService.class);
...
}
#Test
public void mytest(){
testSubject.setTimeService(timeServiceMock);
...
}
}