Search code examples
javaunit-testingdependency-injectionmockitoguice

Mock and having real object for testing purposes using Guice


How do I create an object in a Guice Test module that is used as a mock in one test, but requires to be real object in another.

eg. Consider I have a class called ConfigService. This is injected into another class called UserService using constructor injection. During testing, I use a TestModule which has various classes and their mocks.

TestModule.java:

public class TestModule extends AbstractModule{
    @Override
    public void configure() {
            ConfigService configService = Mockito.mock(ConfigService.class);
            bind(ConfigService.class).toInstance(configService);

            UserService userService = new UserService(configService);

            bind(UserService.class).toInstance(userService);

    }
}

In UserServiceTest, I create an injector and use the instances from this TestModule.

Injector injector = Guice.createInjector(new TestModule());
userService = injector.getInstance(UserService.class);
configService = injector.getInstance(ConfigService.class);

This works fine, the place where I face a problem now is when I need to test ConfigService.class.

If I want to use the same TestModule for the ConfigServiceTest, how do I now change the mock object of ConfigService I created earlier to an actual one for testing. The vice versa is also a problem -> ie. if I have a real object of ConfigService, how do I stub and mock the responses in UserService.class.

Is there a way to achieve this or should I be creating separate test modules for mocks and real objects? Or am I going about the entire process in a wrong way?


Solution

  • You can do that using spy method.

    ConfigService realConfigService = new ConfigService();
    ConfigService configService = Mockito.spy(realConfigService);
    bind(ConfigService.class).toInstance(configService);
    

    What spy does is, whenever you provide stubbing, it will behave as if the object is mocked. Otherwise, it will call the real method of the object.

    Please check this answer for more in-depth theory.