Inject a dependency inside an object - scala

I'm new to the Play framework and scala and I'm trying to inject a dependency inside a companion object.
I have a simple case class, like:
case class Bar(foo: Int) {}
With a companion object like:
object Bar {
val myDependency =
if (isTest) {
// Mock
}
else
{
// Actual implementation
}
val form = Form(mapping(
"foo" -> number(0, 100).verifying(foo => myDependency.validate(foo)),
)(Bar.apply)(Bar.unapply))
}
This works fine, but it's not really a clean way to do it. I'd like to be able to inject the dependency at build time so that I can inject different mock objects when testing and different real implementations in development and production.
What's the best way to achieve this?
Any help really appreciated. Thanks!

Along the lines of the Cake, we can try to change your example to
trait Validator {
def validate(foo: Int): Boolean
}
trait TestValidation {
val validator = new Validator {
def validate(foo: Int): Boolean = ...
}
}
trait ImplValidation {
val validator = new Validator {
def validate(foo: Int): Boolean = ...
}
}
trait BarBehavior {
def validator: Validator
val form = Form(mapping(...))(Bar.apply)(Bar.unapply)
}
//use this in your tests
object TestBar extends BarBehavior with TestValidation
//use this in production
object ImplBar extends BarBehavior with ImplValidation
You should additionally try and test if this example fits well within the Play Framework, too

Related

Mock a function within Scala object using Mockito

I have a similar problem as mentioned in link: How to mock a function within Scala object using Mockito?
I have an object FooInner with method stringData, which takes int and give string output
object FooInner {
def stringData(data: Int): String = {
data match {
case 1 => "one"
case _ => "else"
}
}
}
Another object, FooOuter, calls FooInner to get string data and perform some operation on it.
object FooOuter {
def dummyCall(data: Int): String = {
FooInner.stringData(data) + "some operation"
}
}
My aim is to test method FooOuter.dummyCall for string data, NOT returned by FooInner.stringData
For same, I followed above mentioned post and created trait
trait TFooInner {
def stringData(data: Int): String
}
Changed signature of FooInner to
object FooInner extends TFooInner {..}
And created test class FooTests
class FooTests extends FlatSpec with Matchers with MockitoSugar{
"dummyCall" should "mocked data" in {
val service = mock[TFooInner]
when(service.stringData(1)).thenReturn("1") // mocked service data -> 1
assert(FooOuter.dummyCall(1) === "1-some operation") // TestFailedException: "[one]-some operation" did not equal "[1]-some operation"
}
}
, but I am still not able to get mocked service data "1".
I have following questions:
How can I make FooOuter testable with data, not returned from FooInner
Is it right functional style to code in Scala? What I feel is FooOuter is now tightly-coupled/dependent on FooInner
Scala: 2.11
Mockito: 1.9.5
You have to alter both Inner and Outer objects to make them testable.
In general, you should never invoke object methods directly, if you might want to stub them for testing. Such methods should be implemented and accessed via instance calls:
class FooInner {
def stringData(data: Int): String = { ... }
}
object FooInner extends FooInner
class FooOuter(inner: FooInner) {
def dummyCall(data: Int): String = inner.stringData(data) + "bar"
}
object FooOuter extends FooOuter(FooInner)
Now, in your test, you can do
val inner = mock[FooInner]
val testMe = new FooOuter(inner)
when(inner.stringData(any)).thenReturn("foo")
testMe.dummyCall(1) shouldBe "foobar"
verify(inner).stringData(1)

Why there is need to provide injected arguments while creating object of class?

I have a doubt related to dependency injection using Google Guice.
I have a trait which has few implemented methods
trait ATrait {
def someMethodA(parameters: ArgType) = {
//code
}
def someMethodB(parameters: ArgType) = {
//code
}
}
object A extends ATrait
Now I have a class B, where I need methods of Atrait. So I have injected it.
class B #Inject(a: ATrait) {
//code
}
I have also given the binding in Guice module class.
class GuiceModule extends AbstractModule {
override def configure(): Unit = {
bind[ATrait].toInstance(A)
}
}
Now when I create an object of class B,
val b = new B()
It won't let me do that, so my question is if I have to pass manually object of ATrait. What is the use of Google Guice Injection?
I might have done some mistake because I am learning this. Please guide me if I have not understood something correctly.
Thanks in advance.
Guice doesn't work in that way. If you want a new root object you need to ask Guice for a new instance.
val injector = Guice.createInjector(new GuiceModule())
val a:ATrait = injector.getInstance(classOf[ATrait])

Injecting playFramework dependancies to scala object using MacWire traits fail

Lets say I have bunch of car objects in my project, for example:
object Porsche extends Car {
override def start() {...}
override def canStart(fuelInLitr: Int) = fuelInLitr > 5
override val fuelInLitr = 45
override val carId = 1234567
}
im extending Car which is just a trait to set a car structure:
trait Car {
def start(): Unit
val canStart(fuel: Double): Boolean
val fuelInLitr: Int
val carId: Int
}
Now, in the start() method I want to use some api service that will give me a car key based on its id so I cant start the car.
So I have this CarApiService:
class CarApiService (wsClient: WSClient, configuration: Configuration) {
implicit val formats: Formats = DefaultFormats
def getCarkey(carId: String): Future[Option[CarKey]] = {
val carInfoServiceApi = s"${configuration.get[String]("carsdb.carsInfo")}?carId=$carId"
wsClient.url(carInfoServiceApi).withHttpHeaders(("Content-Type", "application/json")).get.map { response =>
response.status match {
case Status.OK => Some(parse(response.body).extract[CarKey])
case Status.NO_CONTENT => None
case _ => throw new Exception(s"carsdb failed to perform operation with status: ${response.status}, and body: ${response.body}")
}
}
}
}
I want to have the ability to use getCarkey() in my car objects, so I created a CarsApiServicesModule which will give my access to the carApiService and I can use its methods:
trait CarsApiServicesModule {
/// this supply the carApiService its confuguration dependancy
lazy val configuration: Config = ConfigFactory.load()
lazy val conf: Configuration = wire[Configuration]
/// this supply the carApiService its WSClient dependancy
lazy val wsc: WSClient = wire[WSClient]
lazy val carApiService: CarApiService = wire[CarApiService]
}
and now I want to add mix this trait in my car object this way:
object Porsche extends Car with CarsApiServicesModule {
// here I want to use myApiService
// for example: carApiService.getCarkey(carId)...
}
but when compiling this I get this error:
does anyone know what is the issue?
also, is that design make sense?
You need to keep in mind that wire is just a helper macro which tries to generate new instance creation code: it's quite dumb, in fact. Here, it would try to create a new instance of WSClient.
However, not all objects can be instantiated using a simple new call - sometimes you need to invoke "factory" method.
In this case, if you take a look at the readme on GitHub, you'll see that to instantiate the WSClient, you need to create it through the StandaloneAhcWSClient() object.
So in this case, wire won't help you - you'll need to simply write the initialisation code by hand. Luckily it's not too large.

Scala: reconfigure trait using CLI parameters

I have a Scala application, where pretty much every object extends a specific trait, which holds all the main functions and variables used by pretty much the entire system.
I want to add a --testing flag to my app's command line variables, which will shift the the results of some of the functions in the trait.
Putting it simply, I'd like the variable accepted in the main to have an affect that alters something in the trait before it is extended by the objects - without sending it explicitly to all objects.
Any ideas how that can be performed?
I doubt you really want to dynamically modify a trait, and I am not sure if it possible that all your classes inheriting that trait would be affected. I don't know enough about the compiler and byte code.
A way to accomplish something similar would be to have your trait take a parameter, and make your trait act conditionally on the parameter.
trait Foo {
val testing: Boolean
def fn1(): Unit = {
if (testing) {
println("testing")
} else {
println("production")
}
}
}
class Bar(val testing: Boolean) extends Foo {
def fn2(): Unit = {
fn1()
}
}
new Bar(true).fn2()
new Bar(false).fn2()
Your question is broad and this is just my 5 cents.
Update
trait Foo {
def fn1(): Unit = {
if (Foo.testing) {
println("testing")
} else {
println("production")
}
}
}
object Foo {
var testing: Boolean = false
}
class Bar extends Foo {
def fn2(): Unit = {
fn1()
}
}
object SOApp extends App {
new Bar().fn2()
Foo.testing = true
new Bar().fn2()
}
Consider passing the 'testing' flag to the trait's initializer block like this:
trait MyTrait {
var testMode: Boolean = _
def doSomething(): Unit = {
if (testMode)
println("In Test Mode")
else
println("In Standard Mode")
}
}
// IMPORTANT: Your best bet would be to create some Config object
// that is loaded and initialized in a main method.
// Define test-specific Config class:
case class Config(testMode: Boolean) {
def isTestMode: Boolean = this.testMode
}
// Instantiate in main method:
val config = new Config(true)
// Later, extend the trait:
class MyObj extends MyTrait { testMode = config.isTestMode() }
// Then just invoke
new MyObject().doSomething()

Abstract fields for dependency injection

In Scala, is there there anything wrong with using the below method of dependency injection.
// Define an interface
trait FileStorage {
def readFile(filename:String):OutputStream
}
// And an implementation
class S3FileStorage extends FileStorage {
def readFile(filename:String):OutputStream = ???
}
// Define our service as a trait with abstract fields that need to be
// injected in order to construct. All implementation details go here.
trait FileHTTPServer {
val fileStorage:FileStorage
def fetchFile( session:Session, filename:String ) = ???
}
Now we wire things up
// Wire up a concrete file service that we actually use in code
// No implementation details should go here, we're simply wiring up a FileHttpServerl
// An entire project could be wired up this way in a central location if desired.
object S3FileHttpServer extends FileHTTPServer {
val fileStorage = new S3FileStorage
}
// We could also do this anonymously
val myHttpServer = new FileHttpServer {
val fileStorage = new S3FileStorage
}
// Or create a mocked version for testing
val mockedHttpServer = new FileHttpServer {
val fileStorage = mock[FileStorage]
}
Obviously the Cake pattern provides more flexibility (particularly around self-types), however for simpler use cases this has much less boilerplate, while still providing compile time checking and a clean unambiguous interface.
Yes, this is absolutely fine approach. And yes, sometimes you can use constructor injection, nothing wrong with that too. But with constructor injection you have to propagate your dependencies manually, while with cake pattern your dependencies are propagated automatically via self-type annotations. So for big projects constructor injection actually lead to more boilerplate than cake pattern, especially at the construction site (where you create all your objects and set up dependencies between them).
However, what you have presented is not full-fledged cake pattern. In real cake pattern there is an additional layer around business logic classes, so-called components, and you do not wire up logic classes directly but components instead.
trait FileStorageComponent {
def fileStorage: FileStorage
trait FileStorage {
def readFile(filename: String): OutputStream
}
}
trait S3FileStorageComponent extends FileStorageComponent {
val fileStorage = new S3FileStorage
class S3FileStorage extends FileStorage {
def readFile(filename: String): OutputStream = ???
}
}
trait FileHttpServerComponent {
self: FileStorageComponent =>
val fileHttpServer = new FileHttpServer
class FileHttpServer {
def fetchFile(session: Session, filename: String) = ???
}
}
// Wiring
object S3FileHttpServer extends FileHttpServerComponent with S3FileStorageComponent
// Anonymous
val server = new FileHttpServerComponent with S3FileStorageComponent
// Mocking
object TestFileHttpServer extends FileHttpServerComponent with FileStorageComponent {
val fileStorage = mock[FileStorage]
}
In this approach there are more boilerplate in traits definitions, but in return you have greater flexibility and very clear dependency management on the use place. For example, here is how program entry point in one of my projects looks like:
object Main
extends MainUI
with DefaultActorsManagerComponent
with DefaultPreferencesAccessComponent
with DefaultModelComponent
with DefaultMainWindowViewComponent
with DefaultMainWindowControllerComponent
with MainWindowReporterComponent
with DefaultClientActorComponent
with DefaultResponseParserActorComponent
with DefaultArchiverActorComponent
with DefaultMainWindowAccessActorComponent
with DefaultUrlParserComponent
with DefaultListenerActorComponent
with DefaultXmlPrettifierComponent
All main program components are in one place. Pretty neat IMO.