8

Below is my private method in my DataTap class and I am trying to junit test this private method using jmockit -

private void parseResponse(String response) throws Exception {
    if (response != null) {
        // some code
    }
}

So below is the junit test I wrote but for null case, it is throwing NPE somehow on the junit test itself.

DataTap tap = new DataTap();
Deencapsulation.invoke(tap, "parseResponse", "hello");

// this line throws NPE
Deencapsulation.invoke(tap, "parseResponse", null);

So my question is - Is there any way I can pass null string to parseResponse method using JMOCKIT as part of junit testing?

This is what I am seeing on that line -

The argument of type null should explicitly be cast to Object[] for the invocation of the varargs method invoke(Object, String, Object...) from type Deencapsulation. It could alternatively be cast to Object for a varargs invocation

john
  • 11,311
  • 40
  • 131
  • 251
  • That code should work. I think the problem is somewhere else. – tbodt Apr 15 '14 at 23:02
  • This what I can see on that line `The argument of type null should explicitly be cast to Object[] for the invocation of the varargs method invoke(Object, String, Object...) from type Deencapsulation. It could alternatively be cast to Object for a varargs invocation` and it is indeed failing. – john Apr 15 '14 at 23:07

4 Answers4

17

A quick glance at the documentation suggests that what you're trying to do with that signature is not possible:

...if a null value needs to be passed, the Class object for the parameter type must be passed instead

If that's the case, then pass in the Class object as well as the instance.

Deencapsulation.invoke(tap, "parseResponse", String.class);
Makoto
  • 104,088
  • 27
  • 192
  • 230
  • Thanks Makoto. I tried this and I got `Invalid null value passed as an Argument 1`. Any suggestion what's wrong? – john Apr 16 '14 at 03:23
  • 2
    Pass the Class object *instead* of `null`, not in addition to it: `Deencapsulation.invoke(tap, "parseResponse", String.class)`. Because of method overloading, JMockit needs to know the type of each parameter, so that it can find the desired method through Reflection; such a type can only be determined from a non-null argument *or* by explicitly passing it in the call to `invoke(...)`. – Rogério Apr 16 '14 at 16:56
  • Docs now at: http://jmockit.org/tutorial/ReflectionUtilities.html#deencapsulatingMethods – jordanpg Sep 25 '15 at 15:30
  • @jordanpg: Feel encouraged to edit the answer with the new docs. – Makoto Sep 25 '15 at 15:41
  • Answer seems vague. I had to invoke method with null list arg. this worked: Deencapsulation.invoke(theObject, "methodName", List.class); – Josef.B Jun 06 '16 at 01:41
0

Do what the error says. That is, change the line to this:

Deencapsulation.invoke(tap, "parseResponse", (Object) null);
tbodt
  • 16,609
  • 6
  • 58
  • 83
  • Thanks tbodt. I tried this and I got `Invalid null value passed as an Argument 0`. Any suggestion what's wrong? – john Apr 16 '14 at 03:28
0

I did like that when I need to pass null String in toString method i.e via casting the null into required type

mockedObject.toString((String) null)
ABC
  • 4,263
  • 10
  • 45
  • 72
0

You are using the convenience method and you need to use the full method. There are two methods to invoke a method on an object instance. The first method works by getting the parameterTypes from the nonNullArgs.

Deencapsulation.invoke(instance, methodName, nonNullArgs);
Deencapsulation.invoke(instance, methodName, parameterTypes, methodArgs);

You need to pass in the parameterTypes if one of the args is null like this:

DataTap tap = new DataTap();
String response = null;
Class[] parameterTypes = { String.class };
Deencapsulation.invoke(tap, "parseResponse", parameterTypes, response);
pamcevoy
  • 1,136
  • 11
  • 15