3

I am trying to test the following class:

public final class ClassA {

  private final ClassB member;

  public ClassA() {
    this.member = new ClassB();
  }

}

The following is the test class:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassA.class, ClassB.class})
public final class ClassATest {

  @Mock
  private ClassB mocked;

  private ClassA testClass;

  @Before
  public void initTest() {
    PowerMockito.whenNew(ClassB.class).withNoArguments().thenReturn(mocked);
    testClass = new ClassA();
  }

Now, the problem is that I get a nullpointerexception, whose stacktrace looks like:

java.lang.NullPointerException
  [junit]     at a.a.i.ClassA.<init>(ClassA.java:44)
  [junit]     at a.a.i.ClassATest.init(ClassATest.java:53)
  [junit]     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  [junit]     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  [junit]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  [junit]     at java.lang.reflect.Method.invoke(Method.java:606)
  [junit]     at org.junit.internal.runners.MethodRoadie.runBefores(MethodRoadie.java:132)
  [junit]     at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:95)
  [junit]     at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294)
  [junit]     at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127)
  [junit]     at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82)
  [junit]     at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
  [junit]     at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:86)
  [junit]     at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
  [junit]     at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)
  [junit]     at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
  [junit]     at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
  [junit]     at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:33)
  [junit]     at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:45)
  [junit]     at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:122)
  [junit]     at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:106)
  [junit]     at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
  [junit]     at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
  [junit]     at junit.framework.JUnit4TestAdapter.run(JUnit4TestAdapter.java:38)
  [junit]     at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:532)
  [junit]     at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.launch(JUnitTestRunner.java:1165)
  [junit]     at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:988)

Line 44 of ClassA is public ClassA() {

And Line 52 of ClassATest is testClass = new ClassA();

I have never before encountered a NullPointerException at the constructor definition, so I have no idea what to make of it. Any help will be appreciated.

alpha_ulrich
  • 536
  • 5
  • 21

3 Answers3

0

I know that question is about NPE, but instead of solving this problem you should rethink your testing strategy. Why?

If ClassA is responsible for creation and life of the instance of ClassB and you decide to NOT inject object of the ClassB why you try to mock it? Your tests should not depend on implementation details so you should not mock ClassB if you are not injecting it anywhere.

0

That approach is not recommendable at all. Objects should not be responsible of creating its own dependencies. They should be provided in their constructor (or via setter methods).

I would recommend you to change your constructor like this

public final class ClassA {

  private final ClassB member;

  public ClassA(ClassB member) {
    this.member = member;
  }

}

In case you want to keep your code you could add a constructor to be used in tests (although adding code only for testing purposes isn't recommendable either)

public final class ClassA {

  private final ClassB member;

  public ClassA() {
    this(new ClassB());
  }

  // Default visibility so it's only visible in its package
  // Added for testing purposes
  ClassA(ClassB member) {
    this.member = member;
  }

}
Alberto S.
  • 7,409
  • 6
  • 27
  • 46
-3

i guess when you declared member as final u should instantiate it right away try to do that before going to the constructor and see what happens

Méhdi Màick
  • 157
  • 3
  • 7
  • 5
    You guess wrong. `final` instance fields can be set in the constructor. (In general, *guesses* are not useful answers.* – T.J. Crowder Feb 27 '16 at 11:49