JUnit testing of Ratpack server with Guice injection

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

JUnit testing of Ratpack server with Guice injection

Roman
Hi,

I am trying to write a JUnit test with service dependencies being injected.


```
    protected MainClassApplicationUnderTest aut = new MainClassApplicationUnderTest(App.class) {
        @Override
        protected void addImpositions(final ImpositionsSpec impositions) {
            impositions.add(UserRegistryImposition.of(appRegistry -> {
                // Allow modifying Injector in tests
                return appRegistry.join(Guice.registry(injector));
            }));
        }
    };

    private Injector injector = com.google.inject.Guice.createInjector(new Module());

    @Before
    public void setup () {
        injector.injectMembers(this);
    }

    @After
    public void tearDown() {
        aut.close();
    }
```

and then using injected services in my test classes:

```
    @Inject
    private UserService userService;
```


This was working fine until I started adding persistence to my app with HikariModule. Now Guice registry creation is a bit more complex:

```
                    .join(Guice.registry(b -> b
                            .module(HikariModule.class, hikariConfig -> {
                                final String dbUrl = System.getenv("JDBC_DATABASE_URL");
                                hikariConfig.setJdbcUrl(dbUrl);
                            })
                            .module(Module.class)
                            .bind(DbMigrator.class)
                        ).apply(r))
```

Because my registry now consists of multiple modules if I have a service that depends on DataSource class coming from HikariModule guice injection fails in tests.

My goal is to allow writing tests in the following fashion:

```

    private UserService userService; // <- Inject it somehow from Application under test

   @Test
    public void testUser() {
        final Result<User, String> userResult = userService.create(new User.Registration());
        final ReceivedResponse res = aut.getHttpClient().get("/users/" + user.userId);
        assertEquals(200, res.getStatusCode());
   }
```


What is the right approach of injecting service dependencies in tests? I would very much prefer reusing guice modules from MainClassApplicationUnderTest rather than creating my own and overriding them.



       
Reply | Threaded
Open this post in threaded view
|

Re: JUnit testing of Ratpack server with Guice injection

Roman
After quite some time battling with this issue and help from Ratpack slack I managed to pull this off.

First of all we need to capture our application registry in the local variable.
   
```
    private Registry appRegistry;

    protected MainClassApplicationUnderTest aut = new MainClassApplicationUnderTest(App.class) {
        @Override
        protected void addImpositions(final ImpositionsSpec impositions) {
            impositions.add(UserRegistryImposition.of(r -> {
                appRegistry = r;
                return Registry.empty();
            }));
        }
    };
```

It turns out there is a nifty method that starts the application. So when injecting the class we will know that `Registry` will not be null and we can inject classes.

```
    protected <T> T inject(final Class<T> classOf) {
        aut.getAddress();
        return appRegistry.get(classOf);
    }
```

Then in test classes we can simply inject any class that is present in the registry.

```
    final UserService userService = inject(UserService.class);
    // OR
    final DataSource dataSource = inject(DataSource.class);
```