Dawson Smith
Dawson Smith

Reputation: 531

How to mock an object with Guice @Inject?

I have a class A and a class B.

public class A{
    @Inject // Guice Inject
    private B b;
}

The test class looks like -

public class ATest{
    private B b;
    
    private A a;

    @Before
    public void setup() {
        b = Mockito.mock(b.class);
        a = new A();
    }
}

The thing is that class B isn't getting mocked. In the test class, there's a NullPointerException whenever a method of B is getting invoked. I can't make changes to class A. Please help me out on how to mock class B successfully?

Upvotes: 1

Views: 3961

Answers (1)

ouid
ouid

Reputation: 433

I assume that in your case it's not that B isn't mocked, but that it is not injected into a.

One way to have it injected would be to create a Guice Injector in the test with a Module, which would bind a Class to be injected, B in your case, to a concrete instance of B, and then use Injector#injectMembers(a) to have b injected into a.

Working example:

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

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;

class InjectableTest {
  private static class Service {
    @Inject
    private Object obj;

    public Object getObj() {
      return obj;
    }
  }

  private final Object obj = Mockito.mock(Object.class);
  private final Injector injector = Guice.createInjector(new AbstractModule() {
    @Override
    protected void configure() {
      bind(Object.class).toInstance(obj);
    }
  });

  @Test
  void t() {
    Service s = new Service();
    injector.injectMembers(s);
    Assertions.assertEquals(obj, s.getObj());
  }
}

If you need to do it more often than only for one test, have a look at the answers of this question, which discuss different ways of Guice dependency injection in unit tests.

Upvotes: 3

Related Questions