Mocking a method inside a private method - java

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

Related

Writing a Junit test for a boolean method with no parameters

I have a class where I want to write a junit test for.
This method has no parameters, can this method accordingly?
public class classTobeTested {
#Self
SlingHttpServletRequest request;
static final String keyword = "hello";
public boolean isActive() {
boolean check;
String pathChecker;
pathChecker = (request.getRequestURL()).toString();
check= pathChecker.contains(keyword);
return check;
}
}
This would be the testing class i had in mind
#RunWith(MockitoJUnitRunner.class)
public class testclasstobetested {
#Test
public void TestclassTobeTested() throws Exception{
classTobeTested CTT = new classTobeTested();
assertFalse(CTT.isActive("hello how are you"));
}
}
I know my method does not take a parameter but has strings declared inside the method.
How can i use assertFalse correctly to test a non param method.
Using annotations and Junit4 you can do it like this:
#RunWith(MockitoJUnitRunner.class)
public class testclasstobetested {
#InjectMocks
private classTobeTested CTT;
#Mock
private SlingHttpServletRequest request;
#Test
public void TestclassTobeTested() throws Exception{
when(request.getRequestURL()).thenReturn(new StringBuffer("hello how are you"));
assertFalse(CTT.isActive());
}
}

Mockito - Impossible stubbing mocked object

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.

Test concrete method of an abstract class containing an interface call

I have a class:
public abstract class Foo{
#Inject
private FooBarClient foobarclient;
public abstract long dofoo1();
public abstract long dofoo2();
public void doBar1(){
foobarClient.docall(faa);
}
}
I'd like to test the doBar1() method so I made my test class like this:
#RunWith(MockitoJUnitRunner.class)
public class FooTest {
private Foo foo;
#Mock
private FoobarClient foobarClient;
#Before
public void init() {
foo = new Foo() {
dofoo1(){};
};
}
#Test
public void testControleValiditeSite() throws Exception {
// G
Response response=....;
Mockito.when(foobarClient.docall(Mockito.any(faa.class))).thenReturn(
response);
// W
foo.doBar1();
// T;
}
But I got a null pointer exception on the fooBarclient in doBar1().
I also tried to mock the abstract with:
Foo foo = Mockito.mock(Foo,Mockito.CALLS_REAL_METHODS);
Is there a better method to do this test?
EDIT :
I used reflection. Now the code looks like:
#RunWith(MockitoJUnitRunner.class)
public class FooTest {
private Foo foo;
#Mock
private FoobarClient mockedFoobarClient;
#Before
public void init() {
foo = new Foo() {
dofoo1(){};
};
**MockitoAnnotations.initMocks(this);**
**ReflectionTestUtils.setField(foo , "foobarClient", mockedFoobarClient);**
}
#Test
public void testControleValiditeSite() throws Exception {
// G
Response response=....;
Mockito.when(foobarClient.docall(Mockito.any(faa.class))).thenReturn(
response);
// W
foo.doBar1();
// T;
}
You might not need to mock it, just create an instance in your test (assuming you're able to change the access type of client from private to protected).
Foo foo = new Foo() {
#Override
public long dofoo1() {
return 0;
}
#Override
public long dofoo2() {
return 0;
}
public void setClient(FooBarClient client) {
foobarclient = client;
}
};
foo.setClient(client);
foo.doBar1();
In your test class, create a non-abstract inner class that extends Foo. Use that in your test.

Test argument of a void method with Mockito

Is it possible to test the values of an instance passed as an argument to a method that is void using Mockito?
public String foo() {
Object o = new ObjectX();
o.setField("hi");
someDao.boo(o);
return "response";
}
boo is void and I want to test that foo sets the field to "hi"
Perhaps you would want to use doNothing method.
#Mock
SomeDao someDao;
#Captor
ArgumentCaptor<ObjectX> captor;
#Test
void test() {
doNothing().when(someDao).boo(captor.capture());
foo();
assertEquals("hi", captor.getValue().getField());
}
Updated
this is what JB in my comments is suggesting.
#RunWith(MockitoJUnitRunner.class)
public class BarTest
{
#Mock
private SomeDao someDao;
#InjectMocks
private Bar bar;
#Before
public void initMocks()
{
MockitoAnnotations.initMocks(this);
}
#Test
public void testFoo()
{
Mockito.doAnswer(new Answer<Object>()
{
#Override
public Object answer(InvocationOnMock invocation) throws Throwable
{
ObjectX x = (ObjectX) invocation.getArguments()[0];
Assert.assertEquals("hi", x.getField());
return null;
}
}).when(someDao).boo(Mockito.any(ObjectX.class));
Assert.assertEquals("response", bar.foo());
}
}
This below is my first answer and correct in its own way.
No it's not possible with Mockito, since ObjectX is a new Object within the void method, to accomplish this with Mockito then you would have to pass ObjectX in as an argument to the method foo(). You might want to look into Powermock if your code can't be changed.
public String foo(ObjectX objectX) {
Object o = objectX;
o.setField("hi");
someDao.boo(o);
return "response";
}
Test case
#Test
public void testFoo()
{
ObjectX mock = Mockito.mock(ObjectX.class);
Assert.assertEquals("response", foo(mock));
Mockito.verify(mock, Mockito.times(1)).setField(Mockito.eq("hi"));
}

How to call real methods in class instances annotated with #Injectable in JMockit?

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() {
}
};

Categories