I am testig a public method and I want to verify if a private method, that have mocked params, is called.
All the answers I have found are using invoke method, but this was removed since JMockit v1.36
public class ClassToTest{
public void methodToTest(){
DependencyClass abc = new DependencyClass();
if(privateMethod1()){
privateMethod2(abc);
}
}
private boolean privateMethod1(){ return true; }
private void privateMethod2(DependencyClass abc){ abc.doStuff(); }
}
public class testClassToTest{
#Mocked
DependencyClass abc;
#Tested
ClassToTest testedClass;
#BeforeEach
public void setUp() {
testedClass = new ClassToTest();
}
#Test
public void testMethod(){
new MockUp<ClassToTest>() {
#Mock
private boolean privateMethod1() {
return true;
}
};
testedClass.methodToTest();
new FullVerificationsInOrder() {{
abc = new DependencyClass();
//Check here if privateMethod2(abc) gets called once
}};
}
You can use Powermock to mock and verify private methods.
Please check https://github.com/powermock/powermock/wiki/MockPrivate
You have two ways:
To level up your method's scope from private to package-private and after it, your method will become visible in the test.
Refactoring your code and encapsulate the private method to Predicate and after it, you can test your primary method and Predicate separately.
You can't test the private method by Junit.
I am making a unit test for class in my app, it just a simple class and I thought i did everything right but the test failed saying
Wanted but not invoked:
mContextWeakReference.get();
-> at rahmat.com.app.utility.backwardcompatibility.StringResourceUtilTest.getString(StringResourceUtilTest.java:40)
Actually, there were zero interactions with this mock.
this is the class to be tested
public class StringResourceUtil {
private static StringResourceUtil sInstance;
private WeakReference<Context> mContextWeakReference;
public static StringResourceUtil getInstance() {
return sInstance;
}
#Inject
public StringResourceUtil(Context context) {
mContextWeakReference = new WeakReference<>(context);
sInstance = this; //NOSONAR
}
public String getString(int resId) {
return mContextWeakReference.get().getString(resId);
}}
this is unit test I made
public class StringResourceUtilTest {
private StringResourceUtil mResourceUtil;
#Mock
private Context mContext;
#Mock
private WeakReference<Context> mContextWeakReference;
#Before
public void setUp(){
MockitoAnnotations.initMocks(this);
mResourceUtil = new StringResourceUtil(mContext);
}
#Test
public void getString() {
int resId = 123;
mResourceUtil.getString(resId);
verify(mContextWeakReference).get().getString(eq(resId));
}}
any help would be much appreciated, thanks
Your StringUtil class is always creating a new object of mContextWeakReference object and even if you are making it, it won't inject automatically ( for that you use injectMock but no use here, since new object creation always happens internally).
public class StringResourceUtilTest {
private StringResourceUtil mResourceUtil;
#Mock
private Context mContext;
#Before
public void setUp(){
MockitoAnnotations.initMocks(this);
mResourceUtil = new StringResourceUtil(mContext);
// setup mock return type
// mock objects are not real,so need to moeck the behavior of method as well
when(mContext.getString(R.string.a123)).thenReturn("123");
}
#Test
public void getString() {
int resId = R.string.a123;
// check the return type
assertEquals("123",mResourceUtil.getString(resId));
}
}
Note: To verify the internal working, read
What is the difference between mocking and spying when using Mockito?
Because you creating mContextWeakReference = new WeakReference<>(context); in constructor, it will never been a mock in StringResourceUtil.
You can set prepared mock mContextWeakReference by using
org.springframework.test.util.ReflectionTestUtils.setField(mResourceUtil , "mContextWeakReference", mContextWeakReference);
Otherwise you should modifying StringResourceUtil class to be a testable
Is it possible to initialize the object to test not on declaration but in each test case? I can't initialize the object on declaration because the parameters passed to the constructor are part of the test cases. I would need something as:
#TestSubject
private ClassUnderTest classUnderTest;
#Mock
private Collaborator mock;
#Test
public void test12() {
classUnderTest = new ClassUnderTest(1, 2);
replay(mock);
Integer result = classUnderTest.work(3, 4);
// Assertions
}
But if I do the above, Easymock complains:
java.lang.NullPointerException: Have you forgotten to instantiate classUnderTest?
I've taken a look at MockBuilder, but I don't see how it can help in this case.
EasyMock does not support what you're asking for. Other testing libraries do/might support it, though. For example, using JMockit:
#Test
public void test12(
#Injectable("1") int a, #Injectable("2") int b, #Tested ClassUnderTest cut
) {
Integer result = cut.work(3, 4);
// Assertions
}
Of course you can! There are two ways.
In the before:
private ClassUnderTest classUnderTest;
private Collaborator mock;
#Before
public void before() {
classUnderTest = new ClassUnderTest(1, 2);
EasyMockSupport.injectMocks(this);
}
#Test
public void test12() {
classUnderTest = new ClassUnderTest(1, 2);
replay(mock);
Integer result = classUnderTest.work(3, 4);
// Assertions
}
Or the good old way:
private ClassUnderTest classUnderTest;
private Collaborator mock;
#Test
public void test12() {
mock = mock(Collaborator.class);
replay(mock);
classUnderTest.setCollaborator(mock);
classUnderTest = new ClassUnderTest(1, 2);
Integer result = classUnderTest.work(3, 4);
// Assertions
}
I have a Java class named, MyClass, that I want to test with JUnit. The public method, methodA, that I want to test calls a private method, methodB, in the same class to determine which conditional path to follow. My goal is to write JUnit tests for the different paths in methodA. Also, methodB calls a service, so I do not want it to actually be executed when I run the JUnit tests.
What is the best way to mock methodB and control its return so that I can test different paths for 'methodA'?
I prefer to use JMockit when writing mocks, so I am specifically interested in any answer that applies to JMockit.
Here is my example class:
public class MyClass {
public String methodA(CustomObject object1, CustomObject object2) {
if(methodB(object1, object2)) {
// Do something.
return "Result";
}
// Do something different.
return "Different Result";
}
private boolean methodB(CustomObject custObject1, CustomObject custObject2) {
/* For the sake of this example, assume the CustomObject.getSomething()
* method makes a service call and therefore is placed in this separate
* method so that later an integration test can be written.
*/
Something thing1 = cobject1.getSomething();
Something thing2 = cobject2.getSomething();
if(thing1 == thing2) {
return true;
}
return false;
}
}
This is what I have so far:
public class MyClassTest {
MyClass myClass = new MyClass();
#Test
public void test_MyClass_methodA_enters_if_condition() {
CustomObject object1 = new CustomObject("input1");
CustomObject object2 = new CustomObject("input2");
// How do I mock out methodB here to return true?
assertEquals(myClass.methodA(object1, object2), "Result");
}
#Test
public void test_MyClass_methodA_skips_if_condition() {
CustomObject object1 = new CustomObject("input1");
CustomObject object2 = new CustomObject("input2");
// How do I mock out methodB here to return false?
assertEquals(myClass.methodA(object1, object2), "Different Result");
}
}
Thanks!
To give the answer you asked for (using JMockit's partial mocking):
public class MyClassTest
{
#Tested MyClass myClass;
#Test
public void test_MyClass_methodA_enters_if_condition() {
final CustomObject object1 = new CustomObject("input1");
final CustomObject object2 = new CustomObject("input2");
new NonStrictExpectations(myClass) {{
invoke(myClass, "methodB", object1, object2); result = true;
}};
assertEquals("Result", myClass.methodA(object1, object2));
}
#Test
public void test_MyClass_methodA_skips_if_condition() {
final CustomObject object1 = new CustomObject("input1");
final CustomObject object2 = new CustomObject("input2");
new NonStrictExpectations(myClass) {{
invoke(myClass, "methodB", object1, object2); result = false;
}};
assertEquals("Different Result", myClass.methodA(object1, object2));
}
}
However, I would not recommend doing it like that. In general, private methods should not be mocked. Instead, mock the actual external dependency of your unit under test (the CustomObject in this case):
public class MyTestClass
{
#Tested MyClass myClass;
#Mocked CustomObject object1;
#Mocked CustomObject object2;
#Test
public void test_MyClass_methodA_enters_if_condition() {
new NonStrictExpectations() {{
Something thing = new Something();
object1.getSomething(); result = thing;
object2.getSomething(); result = thing;
}};
assertEquals("Result", myClass.methodA(object1, object2));
}
#Test
public void test_MyClass_methodA_skips_if_condition() {
new NonStrictExpectations() {{
object1.getSomething(); result = new Something();
object2.getSomething(); result = new Something();
}};
assertEquals("Different Result", myClass.methodA(object1, object2));
}
}
Do not be tempted to mock private methods, even if you can engaging in trickery to do so using a mocking tool. Private members are implementation details, which you should be free to change. Instead use the non-private API to exercise the class. If this is troublesome, consider moving the troublesome code into a different class, if it is not there already, and use dependency injection to inject a mock implementation of the troublesome code.
Make methodB a member of a separate class, and have a private reference to that class within MyClass.
public class MyClass {
private MyOtherClass otherObject = new MyOtherClass();
public String methodA(CustomObject object1, CustomObject object2) {
if(otherObject.methodB(object1, object2)) {
// Do something.
return "Result";
}
// Do something different.
return "Different Result";
}
}
class MyOtherClass {
public boolean methodB(CustomObject custObject1, CustomObject custObject2) {
// Yada yada code
}
}
Personally, I usually only test public methods and look at coverage reports to ensure that all paths have been visited in my private methods. If I really need to test a private method, that's a smell that requires a refactoring as I have above.
You could also use reflection, but I'd feel dirty doing that. If you REALLY want the solution to that let me know and I'll add it to this answer.
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest({ MyClass.class })
public class MyClassTest {
// Class Under Test
MyClass cut;
#Before
public void setUp() {
// Create a new instance of the service under test (SUT).
cut = new MyClass();
// Common Setup
// TODO
}
#Test
public void testMethodA() throws Exception {
/* Initialization */
CustomObject object2 = PowerMock.createNiceMock(CustomObject.class);
CustomObject object1 = PowerMock.createNiceMock(CustomObject.class);
MyClass partialMockCUT = PowerMock.createPartialMock(MyClass.class,
"methodB");
long response = 1;
/* Mock Setup */
PowerMock
.expectPrivate(partialMockCUT, "methodB",
EasyMock.isA(CustomObject.class),
EasyMock.isA(CustomObject.class)).andReturn(true)
.anyTimes();
/* Mock Setup */
/* Activate the Mocks */
PowerMock.replayAll();
/* Test Method */
String result = partialMockCUT.methodA(object1, object2);
/* Asserts */
Assert.assertNotNull(result);
PowerMock.verifyAll();
}
}
To mock the private method, you need powermock
The sample code will be like this, but I haven't run it.
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith (PowerMockRunner.class)
public class MyClassTest {
#Test
public void test_MyClass_methodA_enters_if_condition() {
final MyClass myClass = Mockito.mock (MyClass.class);
CustomObject object1 = new CustomObject("input1");
CustomObject object2 = new CustomObject("input2");
Mockito.when (myClass.methodB(object1, object2)).thenReturn (true);
Mockito.when (myClass.methodA(object1, object2)).thenCallRealMethod ();
assertEquals(myClass.methodA(object1, object2), "Result");
}
}
I used to rely on Mockito until today I have a final class with some static methods so I've to switched to JMockit. I knew nothing about it before so the question is: how can I apply the similar logic from Mockito to JMockit?
public final class ServiceData extends BaseData {
private List<Data> data;
public ServiceData(List<Data> data) {
this.data = data;
// something else
}
public static Container getContainer() {
return super.getContainer();
}
public Data getDataAt(Index index) {
return super.getContainer().get(index);
}
}
The test written in Mockito looks like:
#Test
public void test() {
ServiceData mockServiceData = mock(ServiceData.class);
Data mockData = mock(Data.class);
// only stubbing some of the methods
Container mockContainer = spy(Container.class);
doReturn(something).when(mockContainer.someMethod());
when(mockServiceData.getContainer()).thenReturn(mockContainer);
when(mockServiceData.getDataAt(any(Index.class)).thenReturn(mockData);
// some assertions
}
This won't work since Mockito cannot mock final classes nor static methods (getContainer)
So how can I write the same logic in JMockit? Thanks.
The following is the JMockit equivalent for the example test:
#Test
public void test(
#Mocked final ServiceData mockServiceData, #Mocked final Data mockData,
#Mocked final Container mockContainer)
{
// only stubbing some of the methods
new Expectations(mockContainer) {{
mockContainer.someMethod(); result = "something";
mockServiceData.getContainer(); result = mockContainer;
mockServiceData.getDataAt((Index) any); result = mockData;
}};
// some assertions
}
To mock static methods the syntax is the same, except that you would write ServiceData.getContainer(); result = mockContainer; instead.