I want to mock private method of a class under test but method return false first two times when the method is called after that it should return false. Here is the code what I tried. This is the class which is being tested
public class ClassToTest
{
public void methodToTest()
{
Integer integerInstance = new Integer(0);
boolean returnValue= methodToMock(integerInstance);
if(returnValue)
{
System.out.println("methodToMock returned true");
}
else
{
System.out.println("methodToMock returned true");
}
System.out.println();
}
private boolean methodToMock(int value)
{
return true;
}
}
Test class
import org.junit.Test;
import static mockit.Deencapsulation.*;
import mockit.*;
public class TestAClass
{
@Tested ClassToTest classToTestInstance;
@Test
public void test1()
{
new NonStrictExpectations(classToTestInstance)
{
{
invoke(classToTestInstance, "methodToMock", anyInt);
returns(false);
times = 2;
invoke(classToTestInstance, "methodToMock", anyInt);
returns(true);
times = 1;
}
};
classToTestInstance.methodToTest();
classToTestInstance.methodToTest();
classToTestInstance.methodToTest();
}
}
I did this to get desired results
final StringBuffer count = new StringBuffer("0");
new NonStrictExpectations(classToTestInstance)
{
{
invoke(classToTestInstance, "methodToMock", anyInt);
result= new Delegate()
{
boolean methodToMock(int value)
{
count.replace(0, count.length(), Integer.valueOf(Integer.valueOf(count.toString())+1).toString());
if(Integer.valueOf(count.toString())==3)
{
return true;
}
return false;
}
};
}
};
For Mockito, there is no direct support to mock private and static methods. In order to test private methods, you will need to refactor the code to change the access to protected (or package) and you will have to avoid static/final methods.
Introduction. First of all, let's talk about what JMockit is: a Java framework for mocking objects in tests (you can use it for both JUnit and TestNG ones). It uses Java's instrumentation APIs to modify the classes' bytecode during runtime in order to dynamically alter their behavior.
Mockito uses 'proxy API' design architecture. 7. JMockit is based on Java 1.5 instrumentation API framework. Finally, the JMockit Testing Toolkit has a wider scope and more ambitious goals than other mocking toolkits, in order to provide a complete and sophisticated developer testing solution.
Using a combination of Expectations and Deencapsulation.invoke(), you can partially mock the tested object:
import org.junit.Test;
import static mockit.Deencapsulation.*;
import mockit.*;
public class TestAClass
{
public static class ClassToTest
{
public void methodToTest()
{
boolean returnValue = methodToMock(0);
System.out.println("methodToMock returned " + returnValue);
}
private boolean methodToMock(int value) { return true; }
}
@Tested ClassToTest classToTestInstance;
@Test
public void partiallyMockTestedClass() {
new Expectations(classToTestInstance) {{
invoke(classToTestInstance, "methodToMock", anyInt);
result = false;
times = 2;
}};
classToTestInstance.methodToTest();
classToTestInstance.methodToTest();
classToTestInstance.methodToTest();
}
}
The test above prints:
methodToMock returned false
methodToMock returned false
methodToMock returned true
In general, of course, we should avoid mocking private
methods. That said, I have found in practice that it is sometimes useful to do so, typically when you have a private method which does something non-trivial and was already tested by another test; in such a case, mocking that private method in a second test (either for a different public method or a different path through the same public method) may be significantly easier than setting up necessary inputs/conditions.
It's just as easy to write the test with a NonStrictExpectations (the original attempt by the OP didn't work only because the same non-strict expectation was recorded twice, with the second recording overriding the first):
@Test
public void partiallyMockTestedClass() {
new NonStrictExpectations(classToTestInstance) {{
invoke(classToTestInstance, "methodToMock", anyInt);
returns(false, false, true);
}};
classToTestInstance.methodToTest();
classToTestInstance.methodToTest();
classToTestInstance.methodToTest();
}
If more flexibility is needed, we can always record a Delegate
-based result:
@Test
public void partiallyMockTestedClass() {
new NonStrictExpectations(classToTestInstance) {{
invoke(classToTestInstance, "methodToMock", anyInt);
result = new Delegate() {
boolean delegate() {
boolean nextValue = ...choose next return value somehow...
return nextValue;
}
}
}};
classToTestInstance.methodToTest();
classToTestInstance.methodToTest();
classToTestInstance.methodToTest();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With