1

I have a class (class B) that's extending a parent class (class A). The parent class has a public method (method X) that calls a method of one of its private member fields (field f > method Y). I'm trying to write a unit test to test a method of class B. However, I have to mock the call to method X that gets inherited by class B. It however gives me a null pointer error when it tries to call method Y in method X. I'm not sure how to mock field f from class B. Could someone please help me with this?

I'm using Mockito to write the test. Field f is autowired. I'd like to avoid adding new code to the file, since it's not my code. I did try:

@Mock
field f;
doReturn(someReturnValue).when(f).Y();

But this doesn't get called. I have a feeling it's because there is no field f in class B.

The current setup is something like this:

class A{
  @Autowired
  private Object f;

  public void X(){
    Map<String, Object> map = new HashMap<>();
    map.putAll(f.Y());  // NPE thrown here
  }
};

class B extends A{
};

Trying to mock field f in my unit test throws a null pointer error at the line where the f.Y() call is made.

user7999116
  • 199
  • 1
  • 12
  • use powermockito. Refer the following post https://stackoverflow.com/questions/28121177/mock-private-method-using-powermockito – franciscecil Jul 06 '19 at 01:49
  • @franciscecil That mocks the return value of a method, not a field member of a parent. If the code which relies on the dependency accesses the field directly rather than uses a getter, that won't work. I don't think Mockito provides any easy way to do this (I could be wrong). You could use reflection to make the field accessible, then assign a mocked value to it. – Vince Jul 06 '19 at 01:51
  • boo to powermockito / powermock. Not saying this as a blanket statement for all code; but for the most part these tools promote avoiding proper dependency injection and writing tests for poor design. If you can't get away with Mockito/ EasyMock it's time to rethink the design. – flakes Jul 06 '19 at 02:31
  • @flakes I'd like to stick with Mockito since the rest of the code base uses it. However, I can't change the current design as it's not in my hands. – user7999116 Jul 06 '19 at 02:42
  • Could you just compose/wrap the class rather than extend it? Adapter pattern is usually a good choice to re-enable mocking and testing the logic you actually write. – flakes Jul 06 '19 at 02:44
  • @flakes I'm not sure what you mean by wrap. Do you have an example that I could look at? I could try. – user7999116 Jul 06 '19 at 03:00
  • Basically you expose the same or similar methods, but you don't extend the base class, you just call in to an instance which is kept as a field of the wrapper class. This means that you can replace the wrapped instance with a mock instance and only test the new logic that is present in your new class. You don't have to worry about what the underlying code is doing and therefore don't have to test it twice (once in the base and once in the extension) – flakes Jul 06 '19 at 03:01
  • See here https://stackoverflow.com/questions/2399544/difference-between-inheritance-and-composition and here https://www.artima.com/designtechniques/compoinh.html – flakes Jul 06 '19 at 03:02
  • @flakes I'll give this a shot – user7999116 Jul 06 '19 at 03:33
  • Mockito does have @InjectMocks annotation which can handle this - see https://github.com/mockito/mockito/blob/release/2.x/src/main/java/org/mockito/InjectMocks.java . BEWARE it can fail silently. See also https://stackoverflow.com/questions/34067956/how-to-use-injectmocks-along-with-autowired-annotation-in-junit and also https://stackoverflow.com/questions/38567326/is-it-discouraged-to-use-spy-and-injectmocks-on-the-same-field – racraman Jul 06 '19 at 04:57
  • Can you share your stack trace when it is failing? – Coder Jul 07 '19 at 14:53

0 Answers0