I want to mock private method, which called from my test method, but instead of mocking, PowerMockito invoke toMockMethod, and I get NPE.
toMockMethod is in the same class.
#RunWith(PowerMockRunner.class)
public class PaymentServiceImplTest {
private IPaymentService paymentService;
#Before
public void init() {
paymentService = PowerMockito.spy(Whitebox.newInstance
(PaymentServiceImpl.class));
MockitoAnnotations.initMocks(this);
}
#Test
public void test() throws Exception {
...
PowerMockito.doReturn(mockedReturn)
.when(paymentService,
"toMockMethod",
arg1, arg2);
}
}
Is it normal situation? What a sense to mock method if it has been invoked?
To enable static or non-public mocking with PowerMock for a class, the class should be added to annotation #PrepareForTest. In your case, it should be:
#RunWith(PowerMockRunner.class)
#PrepareForTest(PaymentServiceImpl.class)
public class PaymentServiceImplTest {
private IPaymentService paymentService;
#Before
public void init() {
paymentService = PowerMockito.spy(Whitebox.newInstance
(PaymentServiceImpl.class));
MockitoAnnotations.initMocks(this);
}
#Test
public void test() throws Exception {
...
PowerMockito.doReturn(mockedReturn)
.when(paymentService,
"toMockMethod",
arg1, arg2);
}
}
I'm gonna leave a second answer for my future self here. There's an alternative problem here. If you're calling Static.method make sure "method" is actually defined in Static and not up the hierarchy.
In my case the code called Static.method, but Static extends from StaticParent, and "method" is actually defined in StaticParent.
#RunWith(PowerMockRunner.class)
#PrepareForTest(StaticParent.class)
public class YourTestClass {
#Before
public init() {
PowerMockito.mockStatic(StaticParent.class);
when(StaticParent.method("")).thenReturn(yourReturnValue);
}
}
public class ClassYoureTesting {
public someMethod() {
Static.method(""); // This returns yourReturnValue
}
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);
//...
}
}
My FixValueConceptIntegration class has a constructor and it looks like this:
private ReferenceConceptHelper referenceConceptHelper;
private ConceptClientFacade conceptClientExternalFacade;
public FixValueConceptIntegration()
{
referenceConceptHelper = JournalSingletonFactory.getInstance().getSingletonInstance(ReferenceConceptHelper.class);
conceptClientExternalFacade = JournalSingletonFactory.getInstance().getSingletonInstance(ConceptClientFacade.class);
}
So now I'm going to test it using Mockito.
If we have a constructor like
public FixValueConceptIntegration(ReferenceConceptHelper referenceConceptHelper, ConceptClientFacade conceptClientExternalFacade)
{
this.referenceConceptHelper = referenceConceptHelper
this.conceptClientExternalFacade = conceptClientExternalFacade
}
I know it is easy to initialize when we are going to testing the class. Because we can just mock the ReferenceConceptHelper and ConceptClientFacade classes.
Then we can use it at the #BeforeMethod like this:
#BeforeMethod
public void beforeMethod()
{
MockitoAnnotations.initMocks(this);
fixValueConceptIntegration = new FixValueConceptIntegration(referenceConceptHelper, conceptClientExternalFacade);
}
Then all the dependencies will inject to the constructor and no worries.
So here the problem is I can't figure out how to inject these dependencies (by mocking) to the above testable class.
Just use the mock (org.mockito.Mockito.mock) method for the class and the when method to mock the method calls:
#Test
public void yourTest() {
ReferenceConceptHelper referenceConceptHelper = mock(ReferenceConceptHelper .class);
when(referenceConceptHelper.someMethod(any()).thenReturn("hello");
ConceptClientFacade conceptClientExternalFacade = mock(ConceptClientExternalFacade.class);
when(conceptClientExternalFacade.someMethod(any()).thenReturn("world");
FixValueConceptIntegration integration = new FixValueConceptIntegration(referenceConceptHelper, conceptClientExternalFacade);
assertEquals("hello world", integration.methodThatYouWouldLikeToTest());
}
In this case, you do not need to use the #BeforeMethod or call MockitoAnnotations.initMocks(this);. For unit tests, the initMocks are only useful if you do not have access directly to the class injected (typically when you are using field injection).
But if you would like to use the annotations (I personally don't like), you can do something like that:
#InjectMocks
private FixValueConceptIntegration integration;
#Mock
private ReferenceConceptHelper referenceConceptHelper;
#Mock
private ConceptClientFacade conceptClientFacade;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
when(referenceConceptHelper.someMethod(any()).thenReturn("hello");
when(conceptClientExternalFacade.someMethod(any()).thenReturn("world");
}
#Test
public void yourTest() {
assertEquals("hello world", integration.methodThatYouWouldLikeToTest());
}
I extended my test class with TestNGBase which extends PowerMockTestCase.
And then add registerMockSingleton method to the TestNGBase class like this;
protected <E, I extends E> void registerMockSingleton(Class<E> typeInterface, I mock)
{
delegate.registerMockSingleton(typeInterface, mock);
}
Then inject mock dependencies to the constructor like this way;
#Override
public void performSetup() {
MockitoAnnotations.initMocks(this);
registerMockSingleton(ReferenceConceptHelper.class,mockReferenceConceptHelper);
registerMockSingleton(ConceptClientFacade.class,mockConceptClientExternalFacade);
fixValueConceptIntegration = new FixValueConceptIntegration();
}
#Override
protected void performTearDown() throws Exception
{
fixValueConceptIntegration = null;
}
All solved!!!
(My testable class constructor doesn't inject dependencies to with constructor
arguments.Thats why I solved my problem like this)
I have:
public class A extends B {
public ObjectC methodToTest() {
return getSomething();
}
}
/* this class is in other project and compiles in project I want test */
public class B {
public ObjectC getSomething() {
//some stuff calling external WS
}
}
and on test:
#RunWith(MockitoJUnitRunner.class)
public class ATest {
#Mock
B bMock;
#InjectMocks
A classTotest;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void getMethodToTestShouldReturnObjectC() {
Mockito.when(bMock.getSomething()).thenReturn(new ObjectC());
assertEquals(classTotest.methodToTest().getClass, ObjectC.class);
}
}
But when I run test Mockito is calling B (and it fails because calls a ws...)
I read a lot of stuff about this but I can't solve it.
¿How Can I mock getSomething() to return ObjectC?
Mockito.when(bMock.getSomething()).thenReturn(new ObjectC());
This method changes only bMock. It doesn't change any other class B (or A) instances.
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 this code in my Subject Under Test:
public class Widget {
private Set<Thing> things;
public Set<Thing> getThings() { return things; }
public void setThings(Set<Thing> things) { this.things = things; }
public void performAction(PerformingVisitor performer) {
for (Thing thing: getThings())
{
thing.perform(performer);
}
}
}
My JUnit/Mockito test looks like:
#RunWith(MockitoJUnitRunner.class)
public class WidgetTest {
#Mock private PerformingVisitor performer;
#Mock private Thing thing;
#InjectMocks private Widget widget;
#Before
public void setUp() throws Exception {
Set<Thing> things = new HashSet<Thing>();
things.add(thing);
widget.setThings(things);
MockitoAnnotations.initMocks(this);
}
#Test
public void shouldPerformThing() {
Mockito.when(thing.perform(Mockito.any(PerformingVisitor.class))).thenReturn(true);
widget.performAction(performer);
Mockito.verify(thing).perform(Mockito.any(PerformingVisitor.class));
}
}
However, this gives me the error:
Wanted but not invoked:
thing.perform(<any>);
-> at com.myclass.ThingTest.shouldPerformThing(WidgetTest.java:132)
I've verified that the code enters the for loop and should be calling the actual thing.perform(performer); line, but my mock does not seem to be recording a call.
I think you need initMocks before the mock injection.
Could you try to change your setUp method for this:
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
Set<Thing> things = new HashSet<Thing>();
things.add(thing);
widget.setThings(things);
}
Hope it works
From the MockitoJUnitRunner javadoc:
Initializes mocks annotated with Mock, so that explicit usage of MockitoAnnotations.initMocks(Object) is not necessary.
So, if you remove
MockitoAnnotations.initMocks(this)
from your setUp method, the test pass.