I am writing a Guice Module and in that module I have a provides method.
class FooModule extends ScalaModule {
#Provides
#Singleton
def providesFoo() : Foo = {
new Foo()
}
}
The problem is that the constructor of new Foo takes a Type Bar as parameter.
I want to know how do I ask guice to give me an instance of Bar so that I can do a new on Foo in the Module
Request those parameters by specifying them as method parameters. From the Provides method wiki documentation:
Dependencies can be passed in as parameters to the method. The injector will exercise the bindings for each of these before invoking the method.
So:
#Provides
#Singleton
def providesFoo(val bar : Bar) : Foo = {
new Foo(bar)
}
Related
Is there a way to invoke a function by default before any other function in a class is called?
I do not want to use frameworks and want to implement in pure Scala.
What I wanted to do is have some function in a class which checks if a user has access to the called method when a method of the same class is called.
This is done in a straightforward way with a private constructor, custom apply and companion object.
case class Foo private (bar: Bar){
def methYouWantToCall: Unit = ???
}
object Foo {
def apply(bar: Bar): Foo = {
val foo = new Foo(bar)
foo.methYouWantToCall
foo
}
}
Hence methYouWantToCall should be sideffecting function with Unit return type.
As you use scala, there are plenty of means of avoiding such ones.
Will default constructor be called in scala if I have #Provides annotation in my Module file to return an object but I never inject it anywhere?
According to official Google Guice documentation: https://github.com/google/guice/wiki/ProvidesMethods
#Provides Methods When you need code to create an object, use an #Provides method. The method must be defined within a module, and it must have an #Provides annotation. The method's return type is the bound type. Whenever the injector needs an instance of that type, it will invoke the method.
So, the constructor will never have been invoked.
If you need to construct the object anyway, use com.google.inject.Singleton annotation:
import com.google.inject._
class DbModule extends AbstractModule {
#Provides
#Singleton
def helloWorld: HelloWorld = new HelloWorld();
}
class HelloWorld() {
println("Hello world!")
}
will print:
Hello world!
I can extend my Scala class Foo with additional methods via an implicit class:
trait Foo {
def bar: String
}
object FooExtensions {
object implicits {
implicit class FooOps(foo: Foo) {
def baz: String = "baz"
}
}
}
But can I mock out those methods?
import org.mockito.Mockito
import org.scalatest.WordSpec
import org.scalatest.mockito.MockitoSugar
class MySpec extends WordSpec with MockitoSugar {
"My mock" should {
"handle methods from implicit classes" in {
import FooExtensions.implicits._
val foo = mock[Foo]
Mockito.when(foo.baz).thenReturn("bix") // fails at runtime
}
}
}
This compiles, but fails with
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
Is it possible to mock methods added via implicit classes? Hopefully with Mockito (or mockito-scala) but I'm interested in any approach that works.
Thing about extension methods, is that they are basically a syntactic sugar:
trait Foo
implicit class ExtensionMethods(foo: Foo) {
def bar: String = "bar
}
foo.bar
is equal to
new ExtensionMethods(foo).bar
So mocking:
Mockito.when(foo.bar).thenReturn("bix")
becomes:
Mockito.when(new ExtensionMethods(foo).bar).thenReturn("bix")
I think there is no workaround - perhaps PowerMock could let you change class constructor..., but with normal Mockito it is impossible.
Usually, it is not a problem though. That is because either:
you put into extension methods behavior, that only depends on extended value and passed parameters (and extended method is quite often pure function that doesn't require mocking) - if you want to change something there, you change input,
if behavior should change, you implement it inside a type class, and make extension method use that type class to inject behavior
trait Bar {
def bar: String
}
object Bar {
implicit val defaultBar: Bar = new Bar { def bar = "bar" }
}
implicit class ExtensionMethods(foo: Foo) {
def bar(implicit bar: Bar): String = bar.bar
}
// in test
implicit var overridenBar: Bar = ...
assert(foo.bar === "sth")
On a side note: the more functional you'll get the less you'll need to mock things as everything will depend only on input passed inside, and a cascade of mocks will become just a code smell - too tight coupling, too large interfaces, etc. Problem is that many Java libraries do not even follow SOLID principles, which makes them both hard to use/test with FP as well as bad OOP on its own. I'm telling this in case you feel mocking is the only way to go in your case.
The only way to achieve that is to use implicit conversions rather than implicit classes
This is a hack intended to show how this could be achieved, but I'd urge to take a look at the code and see why you actually need to do this
So, following your example, you could modify the code to look like this
trait Foo {
def bar: String
}
object FooExtensions {
object implicits {
implicit fooToOps(foo: Foo): FooOps = new FooOps(foo)
class FooOps(foo: Foo) {
def baz: String = "baz"
}
}
}
and your test
import org.scalatest.WordSpec
import org.mockito.MockitoSugar
class MySpec extends WordSpec with MockitoSugar {
"My mock" should {
"handle methods from implicit classes" in {
val fooOps = mock[FooOps]
implicit fooToOps(foo: Foo): FooOps = fooOps
val foo = mock[Foo]
when(foo.baz) thenReturn "bix" // works
}
}
}
the other thing to consider is that in your production you need to get an implicit parameter of the shape Foo => FooOps so when you call that method from the test the actual implicit mock is provided...
As I said, you can make it work like this, but I agree with Mateusz that you shouldn't need to
I would like implement a Guice module which binds an adapter to a named argument, but to create this adapter, it needs to instantiate another class, which also need injected arguments.
Here is the example in Scala:
trait Service
class UserService #Inject()(#Named(value = "foo") foo: String) extends Service
trait Adapter
class AdapterImpl(service: Service) extends Adapter
class AdapterRef(val adapter: Adapter)
class Module extends AbstractModule {
override def configure(): Unit = {
val fooValue = "bar"
bind(classOf[String])
.annotatedWith(Names.named("foo"))
.toInstance(fooValue)
val userService = new UserService(fooValue) //It should be instantiated by Guice somehow
bind(classOf[AdapterRef])
.annotatedWith(Names.named("userService"))
.toInstance(new AdapterRef(new AdapterImpl(userService))) //Thats kinda ok
}
}
Can someone point me to the right direction?
Thank you,
Gabor
You can use a Provides method within your module, which lets you remove the binding. This is my best effort at Scala so if the syntax is incorrect let me know.
#Provides() #Singleton() def provideAdapterRef(service: Service): AdapterRef = {
return new AdapterRef(new AdapterImpl(service))
}
Note the use of Singleton to imitate your examples use of toInstance. If you don't need it to always provide the same instance I would recommend removing the scope and letting it create a new one every time.
An alternative solution is to use a Provider. This requires you to keep a modified version of the binding in your module and create an extra class, but it can be a cleaner solution if your Provider is more complex.
//Can inject UserService as well, or provide annotations to configure which
//implementation of Service you get if you have more than one.
class UserServiceProvider #Inject()(service: Service) extends Provider[AdapterRef] {
override def get(): AdapterRef {
return new AdapterRef(new AdapterImpl(service))
}
}
Then you can change your binding in the module to
bind(classOf[AdapterRef])
.annotatedWith(Names.named("userService"))
.toProvider(classOf[UserServiceProvider])
.in(classOf[Singleton])
Here note the use of in(Singleton) to replicate your toInstance behavior.
I am using Scala + Play and the out of box Guice set up for dependency injection. I am also using Akka Persistence behind the scenes and would like to create a binding for a custom read journal that I can then inject around my application.
Unfortunately, the read journal constructor (which I do not control) requires an explicit reference to the actor system:
PersistenceQuery(actorSystem).readJournalFor[CustomReadJournal]("custom-key")
How do I get a reference to the underlying actorSystem from within a binding definition class (Module)? Is this possible? More generally, is it possible to define interdependent bindings (a la Scaldi?)
My Module class entry currently looks like:
bind(classOf[CustomReadJournal]).toInstance(PersistenceQuery(<what do i put here?>).readJournalFor[CustomReadJournal]("custom-journal"))
Thanks in advance for the help!
If you need to do some kind of logic to create a dependency injection it is useful to use the #Provides annotation. For example:
trait MyProvider {
#Provides
def provideThing(): Thing = {
//make the thing and return it
}
}
class MyModule extends AbstractModule with MyProvider {
override def configure() {
bind(classOf[TraitYYY]).to(classOf[ClassThatTakesThingAsParameter])
}
}
A useful thing to know is that #Provides methods can themselves take parameters and get their arguments injected. For example:
#Provides
def provideThingNeedingParameter(param: P): ThingNeedingParam = {
new ThingNeedingParam(param)
}
Which is relevant to your situation I believe since you want to provide an actor system to an instance of some class.
// You can use #Singleton with #Provides if you need this to be one as well!
#Provides
def provideActorSystem(app: Application): ActorSystem = {
play.api.libs.concurrent.Akka.system(app)
}
#Provides
def providePersistenceQuery(actorSystem: ActorSystem): PersistenceQuery = {
PersistenceQuery(actorSystem)
}
#Provides
def provideCustomReadJournal(persistenceQuery: PersistenceQuery):CustomReadJournal = {
persistenceQuery.readJournalFor[CustomReadJournal]("custom-key")
}
By creating an #Provides annotated method for your CustomReadJournal you can avoid the bind call from configure entirely and control the parameters a bit more. Also, if you need to, #Provides works with #Singleton. I haven't used Akka persistence, but I think this should help you