I have the following set of classes:
public abstract class ParentClass {
#Autowired
private SomeService service;
protected Item getItem() {
return service.foo();
}
protected abstract doSomething();
}
#Component
public ChildClass extends ParentClass {
private final SomeOtherService someOtherService;
#Override
protected doSomething() {
Item item = getItem(); //invoking parent class method
.... do some stuff
}
}
Trying to test the Child class:
#RunWith(MockitoJUnitRunner.class)
public class ChildClassTest {
#Mock
private SomeOtherService somerOtherService;
#Mock
private SomerService someService; //dependency at parent class
#InjectMocks
private ChildClass childClass;
public void testDoSomethingMethod() {
Item item = new Item();
when(someService.getItem()).thenReturn(item);
childClass.doSomething();
}
}
The matter is that I'm always getting a NullPointerException because the parent dependency (SomeService) is always null.
Also tried:
Mockito.doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
return new Item();
}
}).when(someService).getItem();
And using Spy, without any success.
Thanks for your hints.
One option is using ReflectionTestUtils class to inject the mock. In the code bellow I've executed the unit tests with JUnit 4.
#RunWith(MockitoJUnitRunner.class)
public class ChildClassTest {
#Mock
private SomeService someService;
#Test
public void test_something() {
ChildClass childClass = new ChildClass();
ReflectionTestUtils.setField(childClass, "service", someService);
when(someService.foo()).thenReturn("Test Foo");
assertEquals("Child Test Foo", childClass.doSomething());
}
}
Related
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 am trying to unit test a method, which has different branches depending upon the value of an object that is created inside it. The below code demonstrates it.
public class AClass {
public void method2() {
//Some code goes here
}
public void method1(BClass bObject) {
C_Class cObject = bObject.someMethodThatReturnsC();
if(cObject != null) {
method2();
method2();
}
}}
Below is the TestClass:
public class AClassTest {
#InjectMocks
AClass AClassSpy;
#Mock
BClass b_objectMock;
#Mock
C_Class c_objectMock;
#BeforeMethod
public void beforeMethod() {
AClassSpy = spy(new AClass());
MockitoAnnotations.initMocks(this);
}
public void method1Test () {
doReturn(c_objectMock).when(b_objectMock).someMethodThatReturnsC());
AClassSpy.method1(b_objectMock);
verify(AClassSpy, times(2).method2();
}
}
However, it always FAILS, since the c_objectMock is always null. What do I do to tell Mockito to not to return a null object?
It works good, just use #Before annotation from junit, not #BeforeMethod, and mark your test method like #Test and remove second bracket from
doReturn(c_objectMock).when(b_objectMock).someMethodThatReturnsC())<-this one;
and add bracket at verify:
verify(AClassSpy, times(2)<-here.method2();
And just take care of your code!
This should work:
public class AClassTest {
#InjectMocks
private AClass AClassSpy;
#Mock
private BClass b_objectMock;
#Mock
private C_Class c_objectMock;
#Before
public void beforeMethod() {
AClassSpy = spy(new AClass());
MockitoAnnotations.initMocks(this);
}
#Test
public void method1Test() {
doReturn(c_objectMock).when(b_objectMock).someMethodThatReturnsC();
AClassSpy.method1(b_objectMock);
verify(AClassSpy, times(2)).method2();
}
}
Instead of before method you can use annotation #RunWith. It looks clearly:
#RunWith(MockitoJUnitRunner.class)
public class AClassTest {
#Spy
#InjectMocks
private AClass AClassSpy;
#Mock
private BClass b_objectMock;
#Mock
private C_Class c_objectMock;
#Test
public void method1Test() {
doReturn(c_objectMock).when(b_objectMock).someMethodThatReturnsC();
AClassSpy.method1(b_objectMock);
verify(AClassSpy, times(2)).method2();
}
}
You are having this behaviour because you are not mocking property the call to someMethodThatReturnsC.
It should be:
doReturn(c_objectMock).when(b_objectMock).someMethodThatReturnsC();
I have 3 classes:
public class SomeDAO {
// that method I'd want to catch and change
public void getObj() { ... }
}
public class MainService {
private Service2 service2;
public void doMain() {
service2.doSomethingAnother();
}
}
public class Service2 {
private SomeDAO someDAO
public void doSomethingAnother() {
someDAO.getObj();
}
}
All I need - to call doMain but with custom someDao.getObj() inside service2.doSomethingAnother():
public TestClass {
#InjectMocks
private final MainService mainService = new MainService();
#InjectMocks
private final Service2 service2 = new Service2();
#Mock
private SomeDAO someDao;
#Test
public void testMe() {
// substitution
when(someDao.getObj()).thenReturn(new MyObj());
// then I'm calling the outer method
mainService.doMain();
}
}
When running that test I have NPE in mainService.doMain(): service2 in null..
Inside of testMe object service2 is alive and not null, it has been declared as class variable and initialized.
Whether I misundersood #InjectMock behaviour?
Service2 is not injected into MainService, since it is not a mock. Therefore, the server2 attribute of your mainService object is null.
You are also trying to mock too deep. The correct way to test MainService is to mock the dependency of Service2 and not SomeDAO.
A separate test class for Service2 is better where you mock the dependency of SomeDAO.
public TestClass {
#InjectMocks
private MainService mainService;
#Mock
private Service2 service2;
#Before
public void setUp() {
initMocks(this);
}
#Test
public void testMe() {
mainService.doMain();
verify(service2).doSomethingAnother();
}
}
I'm trying to mock a concrete Class using Mockito. However, it remains null in the service under test.
My concrete class and Service:
//My Concrete Class
#Component("supporter")
public class Supporter
{
#Autowired
private IDriver driver;
public int someMethod(int){...}
...
}
//Service Class that uses this abstract class
public class Service implements IService
{
private ExceptionHandler exceptionHandler;
#Autowired
public void setExceptionHandler(ExceptionHandler exceptionHandler) {
this.exceptionHandler = exceptionHandler;
}
private Supporter supporter;
#Autowired
public void setSupporter(Supporter supporter) {
this.supporter = supporter;
}
public int hookItem(int arg)
{
...
//supporter is always null while mock testing <----
int count = supporter.someMethod(arg);
...
return count;
}
}
My Test Code :
public class ServiceTest extends AbstractTestMockito
{
...
IService service = null;
#Mock
private ExceptionHandler exceptionHandler;
#BeforeMethod
public void setup() {
service = new Service();
}
#Test(enabled=true)
public void shouldDoSomething()
{
Supporter supporter = Mockito.mock(Supporter.class);
given(supporter.someMethod(1)).willReturn(new Integer(10));
final int response = service.hookItem(1);
//Assert...
}
}
What could be the reason for it being null?
(My classes/service are Spring beans)
Looking at the test class, it seems like you you are not injecting the mocked Supporter instance into the service instance, e.g. try to add service.setSupporter(supporter); before calling service.hookItem(1).