CuriousCoder
CuriousCoder

Reputation: 1600

Mockito Mock superclass method on a dependency

I have a class with a dependency like this:

public class Subject {
   private Dependency dep;

   public Subject(Dependency d) {
     this.dep = d;
   }

   public Result test() {
     return dep.validate(); 
   }
}

My Dependency class is actually a base class. It looks like this:

public Class Dependency extends Base {
   void method1() {

   }

}

The Base class is an abstract class like this:

public abstract class Base {
  protected abstract method1() {
  }

  //This is the method I want to mock
  public Result validate() {
  }
}

Now, I am trying to test my class Subject:

public class SubjectTest {
  @Mock
  private Dependency dep;

  private Subject subject;

  @Before
  public void setup() {
   initMocks(this);
   subject = new Subject(dep);
  }

  @Test
  public void test() {
    when(dep.validate()).thenReturn(Result.VALID);  //validate is a super class method

    subject.test();
  }
}

When I try to mock the method in when(dep.validate()).thenReturn(Result.VALID) , it actually calls the real super class method and throws a NullPointerException.

How can I solve this issue? I am aware that Composition is to be favored over inheritance, but I have no control over the Dependency class. So, I cannot go and change it.

My team does not favor use of PowerMockito either. So, I cannot use that as well.

Upvotes: 0

Views: 2034

Answers (2)

Mark Bramnik
Mark Bramnik

Reputation: 42541

Probably you've messed something in a setup. I've tried to reproduce your case and it works in my setup:

package com.example.demo;

import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.when;

enum Result {
    VALID, INVALID;
}
abstract class Base {
    protected abstract void method1();

    public Result validate() {
        return Result.INVALID;
    }
}
class Dependency extends Base {
    public void method1() {

    }
}
class Subject {
    private Dependency dep;

    public Subject(Dependency d) {
        this.dep = d;
    }

    public Result test() {
        return dep.validate();
    }
}

public class SampleTest {

    private Dependency dep = Mockito.mock(Dependency.class);

    private Subject subject;


    @Test
    public void testMe() {
        subject = new Subject(dep);
        when(dep.validate()).thenReturn(Result.VALID);  //validate is a super class method

        Result result = subject.test();
        assertThat(result, equalTo(Result.VALID));
    }

}

All-in-all Mockito should support such a use case without any issues.

I suspect that its something with "initMocks"/ or maybe @Mock annotation that requires a special runner/extension if you're on JUnit 5, which is not shown in a question.

I've intentionally avoided these "advanced" features in the example above to create a minimal reproducible example. Please check this code and update whether it works for you.

P.S.: used Mockito-core:3.3.3 for the test

Upvotes: 1

stackguy
stackguy

Reputation: 190

Can't reproduce the error with Java:8, junit:4.12 and mockito:2.1.0, posted code behaves correctly. Double check the versions, maybe.

Upvotes: 1

Related Questions