I am trying to call the real method in my testing class.
there are two methods one is public void m2() and another private void m3() in mapper class.
but here only private method gets execute and public method doesn't gets call.
Sample code is like.
public class Service {
#Autowired
Mapper mapper;
public void m1(String s){
System.out.println(s);
mapper.m1(s);
}
}
public class Mapper {
public String m1(String s){
System.out.println("inside m1 method" +s);
m2();
m3();
return s;
}
public void m2(){
System.out.println("inside m2 public method");
}
private void m3(){
System.out.println("insid m3 private method");
}
}
#RunWith(MockitoJUnitRunner.class)
public class Testing {
#Mock
Mapper mapper;
#InjectMocks
Service service;
#Test
public void test(){
when(mapper.m1(Mockito.any(String.class))).thenCallRealMethod();
service.m1("Check");
}
/**
* #param m1
*/
}
Public method is not called because you don't instruct mock to do so.
Private method is called because mockito doesn't affect private methods (You have to summon dark magic of PowerMock to do so).
Related
I have the below flow
#InjectMocks private ClassToTest classToTest;
#Mock private ClassToInject classToInject;
#Before
public void setup() {
initMocks(this);
}
#Test
public void test() {
Classx mockClassObj = Mockito.mock(Classx.class);
when(classToInject.publicMethod1(mockClassObj)).thenReturn(1000);
classToTest.publicMethod();
}
I want to test public method of classToTest. Now this method makes call to a private method, which I am not mocking. Inside this private method another public method is called, which I want to mock publicMethod1. Instead of the private method making use of value 1000 it is behaving as if the publicMethod1 was not mocked and I get NPE inside the flow of the method somewhere. I tried using #Spy with classToTest and also I am using init.mocks/#RunWith but it fails.
In short it is something like
ClassToTest. publicMethod --> ClassToTest.privateMethod(not mocking) --> ClassToInject.publicMethod1(want to mock)
The class looks like below
class ClassToTest {
#Inject ClassToInject classToInject;
public publicMethod() {
privateMethod();
}
private privateMethod() {
int x = classToInject.publicMethod1();
// use the return value
// throw exception
}
You mock classToInject.publicMethod1(mockClassObj) not classToInject.publicMethod1().
But your code invoked classToInject.publicMethod1();
int x = classToInject.publicMethod1(); // you invoked no parameter method
Check method which you want to invoke.
If You want to invoke classToInject.publicMethod1(), reference this code
#RunWith(MockitoJUnitRunner.class)
public class MockedTest {
#InjectMocks
private ClassToTest classToTest;
#Mock
private ClassToInject classToInject;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() {
Mockito.when(classToInject.publicMethod1())
.thenReturn(1000);
classToTest.publicMethod();
}
}
class ClassToTest{
ClassToInject classToInject;
public void publicMethod() {
privateMethod();
}
private int privateMethod() {
int x = classToInject.publicMethod1();
throw new NullPointerException(String.valueOf(x));
}
}
class ClassToInject{
public int publicMethod1() {
return 0;
}
}
The result is 1000 success
java.lang.NullPointerException: 1000
I want to test a method which creates an object of another class using it's parameterized constructor. Even though I've mocked the constructor of MyClass, it makes the third party library which is in constructor implementation and results in the error. I'm using Mockito/PowerMockito.
public class MyClass{
private MyObj obj;
MyClass (String profile)
{
//some 3rd party library call
obj = thridPartyLib.someMethod(profile);
}
public String someMethod(){
return obj.someExternalCall();
}
}
Class which I want to test
public class ClassTobeTested{
public void execute(){
//some code
// ......
MyClass myClass = new MyClass(profile);
myclass.someMethod();
}
}
What I tried so far - classUnderTest.execute() ends up calling the thridPartyLib.someMethod(profile); which is part of MyClass constructor.
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClass.class)
public class ClassTobeTestedTest {
private MyClass mockMyClass;
private ClassTobeTested classUnderTest;
#Before
public void init() {
classUnderTest = new ClassTobeTested();
mockMyClass = PowerMockito.mock(MyClass.class);
}
#Test
public void testExecute(){
PowerMockito.whenNew(MyClass.class)
.withArguments(Mockito.any())
.thenReturn(mockMyClass);
classUnderTest.execute();
}
}
Your code will work only if you are working with a spy or mock of classUnderTest. Try this. This should work
#RunWith(PowerMockRunner.class)
#PrepareForTest( {MyClass.class, ClassTobeTested.class })
public class ClassTobeTestedTest {
private MyClass mockMyClass;
private ClassTobeTested classUnderTest;
#Before
public void init() {
classUnderTest = spy(new ClassTobeTested());
mockMyClass = PowerMockito.mock(MyClass.class);
}
#Test
public void testExecute() throws Exception {
PowerMockito.whenNew(MyClass.class)
.withArguments(Mockito.any())
.thenReturn(mockMyClass);
classUnderTest.execute();
}
}
The pain might suggest another approach. Consider injecting a Factory into ClassTobeTested which knows how to create an instance of MyObj. For example:
class MyObjFactory {
MyObj create(String profile) {
return new MyClass(profile);
}
}
then
public class ClassTobeTested {
private final MyObjFactory factory;
public ClassTobeTested(MyObjFactory factory) {
this.factory = factory;
}
public void execute(){
//some code
// ......
// MyClass myClass = new MyClass(profile);
MyClass myClass = factory.create(profile);
myclass.someMethod();
}
}
so the unit test becomes simpler with only having to mock the Factory and have it return a mocked MyClass instance. Then it's simple to verify myclass.someMethod() was invoked as expected.
I am newbie in Java world, but it is very hard understand why not can I stub method of a mocked object...
#RunWith(MockitoJUnitRunner.class)
public class ChildBLLIT extends BaseInteractorIT {
#InjectMocks
private ChildBLL ChildBLL = Mockito.mock(ChildBLL.class);
#Before
public void setUp() {
ChildBLL.engine = engineMock;
}
/**
* Test of getZipStatistics method, of class ChildBLL.
*/
#Test
public void testGetZipStatistics() {
final String testZipStatisticsText = "DummyZipStatistics";
//This method will throw the null pointer exception
when(ChildBLL.engine.getZIPStatistics()).thenReturn(testZipStatisticsText);
ChildBLL.getZipStatistics();
verify(ChildBLL.engine).getZIPStatistics();
}
}
When I try to stub the getZIPStatistics() method I get always a null pointer exception, of course I get, because in the getZIPStatistics() method there is an private object, which is not mocked... it seems to me the Mockito does not mocking the private fields... and unfortunately this is from another project:
public class BaseIT {
#Mock
protected static FromOtherProject engineMock;
#Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
}
Here I mocked the engine variable, but then how can I mock/stub the getZIPStatistics() method? This is this method:
public class FromOtherProject {
//...
public final String getZIPStatistics() {
return ZIPStatistics.toString();
}
}
What can I do?
Let's assume a simple class...
public class Account {
public String getPassword() {
return "abc";
}
}
...and simple class that contains it...
public class AccountHolder {
private Account account;
public String getAccountPassword() {
return this.account.getPassword();
}
}
So now we have a simple base class for all Account based tests...
public class AccountBasedTest {
#Mock
protected Account account;
}
...and a class that actually tests the AccountHolder...
#RunWith(MockitoJUnitRunner.class)
public class AccountHolderTest extends AccountBasedTest {
#InjectMocks
private AccountHolder accountHolder;
#Test
public void getAccountPasswort_must_return_account_password() {
Mockito.when( this.account.getPassword() ).thenReturn ("xyz");
Assert.assertEquals("xyz", this.accountHolder.getAccountPassword());
}
}
And that's all. The #InjectMocks, etc. annotations will also look in the superclasses, so you get your mocked account and that account will be put into your AccountHolder. No need to call MockitoAnnotations.initMocks. It shouldn't hurt, but it's not needed because you are using the MockitoJUnitRunner already, which does exactly that.
I have an abstract class, say AbstractClass where I've got a public void method myMethod without an implementation. While I'm testing this class, I've created an anonymous subclass, where I can implement myMethod as I see fit.
In AbstractClass There's another method, say myImplementedMethod which calls myMethod. Is there a trick to what I can put in myMethod in the anonymous subclass, so as to be able to verify that it has been called?
Edit:
I'm using Mockito for mocking, and it is not my place to use another framework.
public abstract class AbstractClass {
public abstract void myMethod();
public void myImplementedMethod() {
myMethod();
}
public class AbstractClassTest {
#Before
public void setUp() {
AbstractClass myClass = new AbstractClass() {
#Override
public void myMethod(){
//What could I put here?
}
}
}
#Test
public void testMyImplementedMethod() {
myClass.myImplementedMethod();
//check that myMethod is called.
}
}
If Mockito's spy works for you, great. However I don't believe it will capture internal method calls. How about the below...
public class AbstractClassTest {
boolean methodCalled = false;
#Before
public void setUp() {
methodCalled = false;
AbstractClass myClass = new AbstractClass() {
#Override
public void myMethod(){
methodCalled = true;
}
}
}
#Test
public void testMyImplementedMethod() {
assertFalse(methodCalled);
myClass.myImplementedMethod();
assertTrue(methodCalled);
}
}
You could create a spy object on your descendant class, call the implemented method and later ensure the not implemented one was called with verify
AbstractClass myInstance= Mockito.spy(myClass);
myInstance.myImplementedMethod();
Mockito.verify(myInstance).myMethod();
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
public class AbstractClassTest {
private AbstractClass myClass;
#Before
public void setUp() {
AbstractClass instance = new AbstractClass() {
#Override
public void myMethod(){}
}
myClass = spy(instance);
}
#Test
public void testMyImplementedMethod() {
myClass.myImplementedMethod();
verify(myClass).myMethod();
}
}
can't you use the reflection api like this
YourClass.getClass().getMethod("myMethod").invoke(obj,args); // pass the appropriate parameters
and if this throws an exception then you havent implemented the method.
I didnt try this myself , if it works do comment .
I'm looking for a way in JMockit to inject the private fields inside a class while maintaining the ability to trigger the real methods. I use #Injectable and #Tested offered by JMockit. But somehow after that the injected instance is not able to call the real method.
Example test:
public class TestClass {
public static class DoSomething {
private Call callee;
public void execute() {
callee.call();
}
}
public static class Call {
public void call() {
System.out.println("real");
}
}
#Tested DoSomething doSomething;
#Injectable Call call;
// nothing happens
#Test
public void testRealCall() {
doSomething.execute();
}
// invocation doesn't help either
#Test
public void testRealCallSecondTry() {
new MockUp<Call>() {
#Mock
#SuppressWarnings("unused")
public void call(Invocation inv) {
inv.proceed();
}
};
doSomething.execute();
}
// this works, but requires redundant methods
#Test
public void testRealCallThirdTry() {
new MockUp<Call>() {
#Mock
#SuppressWarnings("unused")
public void call() {
System.out.println("real");
}
};
doSomething.execute();
}
#Test
public void testFakeCall() {
new MockUp<Call>() {
#Mock
#SuppressWarnings("unused")
public void call() {
System.out.println("fake");
}
};
doSomething.execute();
}
}
Here DoSomething wraps the Call instance, which provides a way to print a message. The ideal output of the four test cases would be:
real
real
real
fake
However the actual scenario is that only 3 and 4 worked, printing:
real
fake
This shows if an instance is created using #Injectable. It's not able to directly call the original method without copying and pasting the old method body to the mocked version. That seems really awkward. Is there a workaround of this?
My understanding is that if you use #Injectable you just get an empty mock and then you can no longer call the original method.
The workaround that I would use is to do the injection "manually" like this:
public class TestClass {
public static class DoSomething {
private Call callee;
public void execute() {
callee.call();
}
}
public static class Call {
public void call() {
System.out.println("real");
}
}
#Tested DoSomething doSomething;
//#Injectable Call call;
// nothing happens
#Test
public void testRealCall() {
Deencapsulation.setField(doSomething, "callee", new Call());
doSomething.execute();
}
// invocation doesn't help either
#Test
public void testRealCallSecondTry() {
new MockUp<Call>() {
#Mock
#SuppressWarnings("unused")
public void call(Invocation inv) {
inv.proceed();
}
};
Deencapsulation.setField(doSomething, "callee", new Call());
doSomething.execute();
}
// this works, but requires redundant methods
#Test
public void testRealCallThirdTry() {
new MockUp<Call>() {
#Mock
#SuppressWarnings("unused")
public void call() {
System.out.println("real");
}
};
Deencapsulation.setField(doSomething, "callee", new Call());
doSomething.execute();
}
#Test
public void testFakeCall() {
new MockUp<Call>() {
#Mock
#SuppressWarnings("unused")
public void call() {
System.out.println("fake");
}
};
Deencapsulation.setField(doSomething, "callee", new Call());
doSomething.execute();
}
}
I ran into this question when I had the same problem. However, the existing answer don't work with newer versions of JMockit.
If a field in the tested class is annotated with #Inject, a corresponding #Injectable is required in the test class. Usually. This means that removing the #Injectable and instead mock the class with MockUp suggested in the other answer doesn't work. JMockit will complain with "Missing #Injectable for field ...".
What needs to be done instead is to change the #Injectable annotation to a #Tested annotation, i.e. change this
#Injectable Call call;
to
#Tested Call call;
call becomes a real instance and JMockit doesn't complain about a missing #Injectable. If you need to mock some methods in call, it can be done with MockUp as usual.
new MockUp<Call>() {
#Mock
public void someMethodToMock() {
}
};