How should one implement a Scaldi Module in regards to testing and mocks (un familiar to that module)?

114 views Asked by At

I have an implicit scaldi Module in my root package object so that any component can use the injector implicitly.

This module looks like this:

val additionalModule = new AtomicReference[Module](new Module {})

lazy val applicationModule = additionalModule.get ++ new Module {
  bind[Trait1] to new Impl1
  bind[Trait2] to new Impl2
} 

The Scaldi documentation says it is not recommended to bind on an already initialised module so I added the additionalModule for testing/module reuse purposes and aggregated it with the predefined one. Did I get it right?

1

There are 1 answers

0
tenshi On

I wouldn't recommend making injector globally accessible. If you would like to use it in particular class, I would recommend you to introduce an implicit parameter with Injector for this class. Something like this:

class UserService(implicit inj: Injector) extends Injectable {
  // ...
}

(more info)

Alternatively you can use a constructor injection in combination with injected macro:

class TokenRepo(db: Database, metrics: Metrics) extends Tokens {
  // ...
}

now you can bind it like this:

class MyModule extends Module {
  bind [Tokens] to injected [TokenRepo]
}

(more info)

When you are testing, it is important not to reuse instances of modules if you are composing them in different ways inside of the tests. This means in your case you need to instantiate not only the test module, but also an application module as well. For instance:

implicit injector = new TestModuleWithMocks ++ new Appmodule

As @Mironor mentioned, you need to be careful with order of the modules in the composition.