How do I use Mockito to mock a protected method? - junit

I’m using Mockito 1.9.5. How do I mock what is coming back from a protected method? I have this protected method …
protected JSONObject myMethod(final String param1, final String param2)
{
…
}
However, when I attempt to do this in JUnit:
final MyService mymock = Mockito.mock(MyService.class, Mockito.CALLS_REAL_METHODS);
final String pararm1 = “param1”;
Mockito.doReturn(myData).when(mymock).myMethod(param1, param2);
On the last line, I get a compilation error “The method ‘myMethod’ is not visible.” How do I use Mockito to mock protected methods? I’m open to upgrading my version if that’s the answer.

This is not an issue with Mockito, but with plain old java. From where you are calling the method, you don't have visibility. That is why it is a compile-time issue instead of a run-time issue.
A couple options:
declare your test in the same package as the mocked class
change the visibilty of the method if you can
create a local (inner) class that extends the mocked class, then mock this local class. Since the class would be local, you would have visibility to the method.

Responding to the request for a code sample of option 3 from John B's answer:
public class MyClass {
protected String protectedMethod() {
return "Can't touch this";
}
public String publicMethod() {
return protectedMethod();
}
}
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
class MyClassMock extends MyClass {
#Override
public String protectedMethod() {
return "You can see me now!";
}
}
#Mock
MyClassMock myClass = mock(MyClassMock.class);
#Test
public void myClassPublicMethodTest() {
when(myClass.publicMethod()).thenCallRealMethod();
when(myClass.protectedMethod()).thenReturn("jk!");
}
}

You can use Spring's ReflectionTestUtils to use your class as it is and without needing of change it just for tests or wrap it in another class.
public class MyService {
protected JSONObject myProtectedMethod(final String param1, final String param2) {
return new JSONObject();
}
public JSONObject myPublicMethod(final String param1) {
return new JSONObject();
}
}
And then in Test
#RunWith(MockitoJUnitRunner.class)
public class MyServiceTest {
#Mock
private MyService myService;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(myService.myPublicMethod(anyString())).thenReturn(mock(JSONObject.class));
when(ReflectionTestUtils.invokeMethod(myService, "myProtectedMethod", anyString(), anyString())).thenReturn(mock(JSONObject.class));
}
}

Something like following worked for me, using doReturn() and Junit5's ReflectionSupport.
[Note: I tested on Mockito 3.12.4]
ReflectionSupport.invokeMethod(
mymock.getClass()
// .getSuperclass() // Uncomment this, if the protected method defined in the parent class.
.getDeclaredMethod("myMethod", String.class, String.class),
doReturn(myData).when(mymock),
param1,
param2);

John B is right, this is because the method you're trying to test is protected, it's not a problem with Mockito.
Another option on top of the ones he has listed would be to use reflection to gain access to the method. This will allow you to avoid changing the method you are testing, and avoid changing the pattern you use to write tests, and where you store these tests. I've had to do this myself for some tests where I was not allowed to change the existing code base which included a large number of private methods that needed to be unit tested.
These links explain Reflection and how to use it very well, so I will link to them rather than copy:
What is reflection and whit is it useful
How to test a class that has private methods, fields, or inner classes

WhiteBox.invokeMethod() can be handy.

public class Test extend TargetClass{
#Override
protected Object method(...) {
return [ValueYouWant];
}
}
In Spring, you can set it high high-priority like this:
#TestConfiguration
public class Config {
#Profile({"..."})
#Bean("...")
#Primary // <------ high-priority
public TargetClass TargetClass(){
return new TargetClass() {
#Override
protected WPayResponse validate(...) {
return null;
}
};
}
}
It is the same to override the origin bean.

Related

doNothing void method with params in other class

I currently have 2 classes:
public class aClass{
public void meth1(){
bClass b = new bClass();
b.meth2();// i dont want to call this method
//buss logic
}
}
public class bClass{
public void meth2(){
// some logic
}
}
Currently I am creating a junit test case for the meth1 in the aClass.
However, I don't want to call the meth2 in the bClass, just execute the busslogic in aClass.
The Classes aClass and bClass are fixed - I cannot(and won't) change the code on aClass and bClass.
I tried many things like #injectmock and doNothing using mokito and power mock, but meth2 is always gets called when I am calling meth1 in aClass.
What can I do to fix this?
You can do this with Powermockito. The link explains all the details. Below is how it might look like for your example.
#RunWith(PowerMockRunner.class)
#PrepareForTest(aClass.class)
public class aClassTesting {
#Mock
bClass mockB;
#Test
public void testMeth1(){
//prepare mocks
whenNew(bClass.class).withNoArguments().thenReturn(mockB);
doNothing().when(mockB).meth2();
//run it
aClass instance = new aClass();
aClass.meth1();
//asserts and verify
verifyNew(bClass.class).withNoArguments();
verify(mockB, times(1)).meth2();
}
}
EDIT:
When you mock out the bClass instance using #Mock then it replaces all the methods in that instance with mock methods. If you only want to mock some of the methods in bCLas, then you must spy the bCLass instance instead of mocking it. Spy only mocks the methods you want. So just replace #Mock with #Spy in my example then only meth2 would be blocked but not any other methods in bClass.
As it stands, with the constraint that you cannot change AClass, then the only solution is to use Powermock (or similar tools) as Jose Martinez mentioned above. On its own, Mockito can't replace constructors (which are treated like static method calls), so your only solution is to rewrite aClass.
For any future readers that find this question who don't have that constraint, a quick refactor of bClass will make this much easier to test.
public class aClass{
public void meth1(){
meth1(new bClass());
}
/** Package private for testing. */
public void meth1(bClass b){
b.meth2();
//buss logic
}
}
At this point, you can pass a mock bClass and call the single-parameter overload to test your business logic. You can also move b.meth2() out of the single-parameter method and into the public parameterless method, if it behaves more like a setup call.
You can use the mockito...
public class aClass {
private final bClass b;
public aClass() {
this.b = new bClass()
}
public aClass(bClass b) {
this.b = b;
}
....
}
#RunWith(MockitoJUnitRunner.class)
public class aClassTest {
#Mock
private final bClass b;
#InjectMocks
private aClass a;
....
}

How to have individual SetUp functions in Junit

I have two test functions and for each I want to have different #Before methods. How to achieve this ?
Although it seems to be convenient to organize all the test under the same class, for your case I think the best option is to separate the tests into different classes, each one with his corresponding setUp.
An alternative (I prefer the previous option) could be call the setUp directly in your test method, like the example as follows:
public class FooTest {
public void setUpMethod1() {
// do setUp things
}
public void setUpMethod2() {
// do setUp things
}
#Test
public void testMethod1() {
setUpMethod1();
// Test
}
#Test
public void testMethod2() {
setUpMethod2();
// Test
}
}
Only as a curiosity (IMO not recomended for your case), you can override the default junit RunListener with your own implementation. Method testStarted is executed before every test and you have access to class and methodName to be able to identify the running test. Dummy sample:
public class MyRunListener extends RunListener {
#Override
public void testStarted(Description description) throws Exception {
//...
Class testClass = description.getClass();
String methodName = description.getMethodName();
//...
}
}
Hope it helps.

how do I use powermockito verifyNew?

Having trouble with this. I've used Powermockito quite a bit in the past. Normally this is pretty smooth. I figured I'd post my problem rather than continue to rummage through examples. So the goal is to verify a call to new for a class. I don't think this is the most popular feature of powermockito.
Here's the test:
import static org.powermock.api.mockito.PowerMockito.verifyNew;
import static org.powermock.api.mockito.PowerMockito.whenNew;
#RunWith(PowerMockRunner.class)
#PrepareForTest(ClassUnderTest.class)
public class VerifyNewTest {
ClassUnderTest myClassUnderTest = new ClassUnderTest();
#Before
public void setUp() throws Exception {
}
#Test
public void test() throws Exception {
whenNew(Collaborator.class).withNoArguments().thenReturn(new Collaborator());
myClassUnderTest.doSomething();
verifyNew(Collaborator.class).withNoArguments();
}
}
and said classes
public class ClassUnderTest {
public void doSomething() {
new Collaborator();
}
}
public class Collaborator {
}
My goal was to make this as simple as possible. I suppose I could have added some mock objects and stubbed some behavior. Anyway, I get.
org.mockito.exceptions.misusing.UnfinishedStubbingException: Unfinished stubbing detected here:
-> at org.powermock.api.mockito.internal.invocationcontrol. MockitoNewInvocationControl.expectSubstitutionLogic(MockitoNewInvocationControl.java:65)
E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, you naughty developer!
Return a mock object in the whenNew() clause would work in your case.
#Test
public void test() throws Exception {
whenNew(Collaborator.class).withNoArguments().thenReturn(mock(Collaborator.class));
myClassUnderTest.doSomething();
verifyNew(Collaborator.class).withNoArguments();
}

Mocking a class in PowerMock

I am using PowerMocking for JUNIT and Iam new to PowerMock.
I want to mock one class which is non static.
The class scenario goes as follows.
public class Export extends MyUtil implements ExportFormatting<DeptSummaryByDCDTO, LmReportsInputDTO>{
public String createPDF(List<DeptSummaryByDCDTO> summaryDtoList, LmReportsInputDTO inputDto){
}
public String createPDF(Map<String, DeptSummaryByDCDTO> paramMap,
LmReportsInputDTO paramK) {
}
}
The calling class is as follows.
public static Response getMultiplePackSku{
filePath = new Export(inputDto).createPDF(resultList,null);
}
The Question is,
I am trying to test the above class using powermock.
Can anybody tell how to mock the line filePath.....
You need to first mock the constructor and return an Export mock. On the returned mock you need to record the call to createPDF. The tricky part is the constructor mocking. I'll give you an example, hopefully you'll get all of it:
#RunWith(PowerMockRunner.class) // This annotation is for using PowerMock
#PrepareForTest(Export.class) // This annotation is for mocking the Export constructor
public class MyTests {
private mockExport;
#Before
public void setUp () {
// Create the mock
mockExport = PowerMock.createMock(Export.class)
}
#Test
public void testWithConstructor() {
SomeDtoClass inputDto = PowerMock.createMock(SomeDtoClass.class);
PowerMock.expectNew(Export.class, inputDto).andReturn(mockExport);
PowerMock.replay(mockExport, Export.class);
expect(mockExport.createPDF(resultList, null);
// Run the tested method.
}
}
Here is a description of how to mock a constructor call: MockConstructor

JMockit mock protected method in superclass and still test method in real child class

I am still learning JMockit and need help understanding it.
I am testing a class that uses superclass methods. My test gets a null pointer when it attempts to use the superclass method due to code inside it that uses struts action context to get the session and pull an object from the session.
The method I want to bypass the struts session stuff inside the protected method.
public class MyExtendingClass extends MySuperClass{
public void methodIamTesting(){///}
}
public abstract class MySuperClass{
//I want to mock this method
protected Object myProtectedSuperClassMethod(){
// struts action context code that returns an object//}
}
Test code
#Test
public void testRunsAndDoesntPass() {
Mockit.setUpMock(MySuperClass.class, new MySuperClass(){
public Object myProtectedSuperClassMethod() {
return object;
}
});
// real class method invocation happens
assertEquals(expected, actual);
}
I keep getting NullPointers just like if I didn't have the mock
Not sure what to try next. All the docs and code samples I have read say to just declare the superclass method as public in the setUpMock and it should work.
I can't mock the entire class because that is the class I am testing.
I discovered that I needed to create the MockClass then reference it using setupmock correctly.
I am really falling in love with JMockit.
#MockClass(realClass = MyExtendingClass.class)
public static class MockSuperClass {
final Object object = new Object();
#Mock
public Object myProtectedSuperClassMethod() {
return object;
}}
#Test
public void testRunsAndNowWillPass() {
Mockit.setUpMock(MySuperClass.class, new MockSuperClass(){
public Object myProtectedSuperClassMethod() {
return object;
}});
// real class method invocation happens where i set expected and actual
assertEquals(expected, actual);
}
you mask the parent class implementation out totally #Mocked final MySuperClass base
abstract class MySuperClass{
protected Object myProtectedSuperClassMethod(){
}
class MyExtendingClass extends MySuperClass{
public void methodIamTesting(){///}
}
#Test
public void testRunsAndDoesntPass(#Mocked final MySuperClass base ) {
//you could mask out all the base class implementation like this
new Expectations(){{
invoke(base, "myProtectedSuperClassMethod");
}};
// real class method invocation happens
// ...
assertEquals(expected, actual);
}