Given the following code:
LinkedList list = mock(LinkedList.class); doCallRealMethod().when(list).clear(); list.clear();
by running this test, a NullPointerException is thrown from the first line in LinkedList # clear:
public void clear() { Entry<E> e = header.next; while (e != header) { Entry<E> next = e.next;
but the header was created earlier:
private transient Entry<E> header = new Entry<E>(null, null, null);
Can anyone explain what happens during mock creation?
####### UPDATE. ######
After reading all the answers, especially Ajay one, I looked at the source code of Objenesis and found out that it uses the Reflection API to create a proxy instance (via CGLIB) and therefore bypasses all the constructors in the hierarchy to java.lang.Object.
Here is a sample code to model the problem:
public class ReflectionConstructorTest { @Test public void testAgain() { try { //java.lang.Object default constructor Constructor javaLangObjectConstructor = Object.class .getConstructor((Class[]) null); Constructor mungedConstructor = ReflectionFactory .getReflectionFactory() .newConstructorForSerialization(CustomClient.class, javaLangObjectConstructor); mungedConstructor.setAccessible(true); //Creates new client instance without calling its constructor //Thus "name" is not initialized. Object client = mungedConstructor.newInstance((Object[]) null); //this will print "CustomClient" System.out.println(client.getClass()); //this will print "CustomClient: null". name is null. System.out.println(client.toString()); } catch(Exception e) { e.printStackTrace(); } } } class CustomClient { private String name; CustomClient() { System.out.println(this.getClass().getSimpleName() + " - Constructor"); this.name = "My Name"; } @Override public String toString() { return this.getClass().getSimpleName() + ": " + name; } }
mhshams
source share