Imagine I have a service:
class ServiceA(serviceB: ServiceB) {
import Extractor._
def send(typeA: A) = serviceB.send(typeA.extract)
}
object Extractor {
implicit class Extractor(type: A) {
def extract = ???
}
}
I want the extract method to be an implicitly defined because it doesn't directly relate to A type/domain and is a solution specific adhoc extension.
Now I would like to write a very simple unit test that confirms that serviceB.send is called.
For that, I mock service and pass a mocked A to send. Then I could just assert that serviceB.send was called with the mocked A.
As seen in the example, the send method also does some transformation on typeA parameter so I would need to mock extract method to return my specified value. However, A doesn't have extract method - it comes from the implicit class.
So the question is - how do I mock out the implicit class as in the example above as imports are not first class citizens.
If you want to specify a bunch of customised extract methods, you can do something like this:
sealed trait Extractor[T] {
// or whatever signature you want
def extract(obj: T): String
}
object Extractor {
implicit case object IntExtractor extends Extractor[Int] {
def extract(obj: Int): String = s"I am an int and my value is $obj"
}
implicit case object StringExtractor extends Extractor[String] {
def extract(obj: String): String = s"I am "
}
def apply[A : Extractor](obj: A): String = {
implicitly[Extractor[A]].extract(obj)
}
}
So you have basically a sealed type family that's pre-materialised through case objects, which are arguably only useful in a match. But that would let you decouple everything.
If you don't want to mix this with Extractor, call them something else and follow the same approach, you can then mix it all in with a context bound.
Then you can use this with:
println(Extractor(5))
For testing, simply override the available implicits if you need to. A bit of work, but not impossible, you can simply control the scope and you can spy on whatever method calls you want.
e.g instead of import Extractor._ have some other object with test only logic where you can use mocks or an alternative implementation.
Related
I'm trying to test an Object.method which contains some nested methods from a Trait apart of some calculations. These nested methods have to be mocked (they access to a DB so I want to mock their responses).
When I call the real Object.method, it should skip the nested methods call and retrieve what I want. I've tried mocking them but test is still calling them.
Here's my example source code:
trait MyTrait {
def myMethodToMock(a: String): String
}
object MyObject extends MyTrait {
def myParentMethod(a:String) = {
val b = myMethodToMock(a)
val c = a + b
c
}
}
Then in my test:
val myTraitMock = mock[MyTrait]
when(myTraitMock.myMethodToMock(a)).thenReturn(b)
//Then I call the parent method:
assert(MyObject.myParentMethod(a) equals c)
It throws a NullPointerException as it's still accessing to myMethodToMock
Your code does not compile, so I am going to guess some things of what you are actually trying to do here ...
You are stubbing a method on a mock, and then calling it on a completely unrelated instance. No wonder it does not work.
A good rule of thumb (and the best practice) is to never mock classes you are actually testing. Split everything you want to mock and test separately into a separate class. This is also known as single responsibility principle (each component should be responsible for a single thing).
trait MyTrait {
def myMethodToMock(a: String): String
}
object MyTrait extends MyTrait {
def myMethodtoMock(a: String) = ???
}
class MyObject(helper: MyTrait = MyTrait) {
def myParentMethod(a: String) = a + helper.myMethodToMock(a)
}
object MyObject extends MyObject()
Now, you can write your test like this:
val myTraitMock = mock[MyTrait]
when(myTraitMock.myMethodToMock(any)).thenReturn("b")
new MyObject(myTraitMock).myParentMethod("a") shouldBe "ab"
verify(myTraitMock).myMethodToMock("a")
The main difference here is that you are passing your mock into the object's constructor, so that when it calls the method, it will be the one you stubbed, not the implementation provided by the default class.
You should use composition rather than inheritance, so you can inject an instance of MyTrait that can be a mock or the real one
I'm was reading about cats and I encountered the following code snippet which is about serializing objects to JSON!
It starts with a trait like this:
trait JsonWriter[A] {
def write(value: A): Json
}
After this, there are some instances of our domain object:
final case class Person(name: String, email: String)
object JsonWriterInstances {
implicit val stringWriter: JsonWriter[String] =
new JsonWriter[String] {
def write(value: String): Json =
JsString(value)
}
implicit val personWriter: JsonWriter[Person] =
new JsonWriter[Person] {
def write(value: Person): Json =
JsObject(Map(
"name" -> JsString(value.name),
"email" -> JsString(value.email)
))
}
// etc...
}
So far so good! I can then use this like this:
import JsonWriterInstances._
Json.toJson(Person("Dave", "dave#example.com"))
Later on I come across something called the interface syntax, which uses extension methods to extend existing types with interface methods like below:
object JsonSyntax {
implicit class JsonWriterOps[A](value: A) {
def toJson(implicit w: JsonWriter[A]): Json =
w.write(value)
}
}
This then simplifies the call to serializing a Person as:
import JsonWriterInstances._
import JsonSyntax._
Person("Dave", "dave#example.com").toJson
What I don't understand is that how is the Person boxed into JsonWriterOps such that I can directly call the toJson as though toJson was defined in the Person case class itself. I like this magic, but I fail to understand this one last step about the JsonWriterOps. So what is the idea behind this interface syntax and how does this work? Any help?
This is actually a standard Scala feature, since JsonWriterOps is marked implicit and is in scope, the compiler can apply it at compilation-time when needed.
Hence scalac will do the following transformations:
Person("Dave", "dave#example.com").toJson
new JsonWriterOps(Person("Dave", "dave#example.com")).toJson
new JsonWriterOps[Person](Person("Dave", "dave#example.com")).toJson
Side note:
It's much more efficient to implicit classes as value classes like this:
implicit class JsonWriterOps[A](value: A) extends AnyVal
This makes the compiler also optimize away the new object construction, if possible, compiling the whole implicit conversion + method call to a simple function call.
I've got the following helper method in my project:
def close(c: Closeable) {
Option(c).foreach(s => Try(s.close))
}
I've got some classes that have a close method but do not implement Closeable. If I change the helper method to use structural types I can still use it on these classes:
def close(c: {def close()}) {
Option(c).foreach(s => Try(s.close))
}
However this introduces use of reflection which is something that I'd like to avoid in runtime.
Is there a way to use something similar to structural typing without inducing runtime reflection?
I.e in the same way Shapeless allows generic access to fields, maybe implicit parameters + macros could be used to access methods in the same way?
Use traits to implement the typeclass pattern.
When I wrote my original solution it was a bit rough round the edges as I assumed a quick search for convert structural bounds to context bounds would pull up better explanations than I could write. That doesn't seem to be the case. Below is a compiling solution.
object Closeables {
trait MyCloseable[A] {
def myClose(a: A): Unit
}
object MyCloseable {
implicit object MyCanBeClosed extends MyCloseable[CanBeClosed] {
def myClose(c: CanBeClosed) = c.nonStandardClose()
}
}
}
class CanBeClosed {
def nonStandardClose(): Unit = println("Closing")
}
import Closeables._
object Test extends App {
def functionThatCloses[A: MyCloseable](a: A) {
implicitly[MyCloseable[A]].myClose(a)
}
def functionThatClosesExplicit[A](a: A)(implicit ev: MyCloseable[A]) {
ev.myClose(a)
}
val c = new CanBeClosed
functionThatCloses(c)
functionThatClosesExplicit(c)
functionThatCloses(c)(MyCloseable.MyCanBeClosed)
functionThatClosesExplicit(c)(MyCloseable.MyCanBeClosed)
}
For each type of class that can be accepted by functionThatCloses you must define and implicit object in MyCloseables.
The compiler looks at the context bound in functionThatCloses and converts it to a function with the definition of functionThatClosesExplicitly.
The compiler than 'finds' the implicit 'evidence' in the definition from the MyCloseables object and uses that.
We've got several types of resources and we wanted to make a method to check if a resource is healthy or not. Given that the type of resources are very heterogeneous we didn't want to use standard subclassing and we decided to use a typeclass:
trait CanHealthCheck[T] {
def isHealthy(t: T): Boolean
}
We also have a utility method to be able to check if a given resource is alive/healthy or not
object LivenessChecker {
def isAlive[T](t: T)(implicit canHealthCheck: CanHealthCheck[T]): Boolean = {
canHealthCheck.isHealthy(t)
}
}
We've got a repository layer to access to the data. We would like to express the idea that a given abstract repository must be "health checkable" but to leave the implementation details to the subclasses implementing the trait:
trait UserRepository {
def findSomeUser(): User = ???
implicit def isHealthCheckable: CanHealthCheck[UserRepository]
}
The problem arises when we want to subclass UserRepository with a particular implementation, given that CanHealthCheck is not covariant on the type T.
class DbUserRepository extends UserRepository {
def ping: Boolean = ???
override implicit val isHealthCheckable: CanHealthCheck[UserRepository] =
new CanHealthCheck[DbUserRepository] {
def isHealthy(db: DbUserRepository) = db.ping
}
}
And this is an example of some dummy function that acts on the abstract repository while trying to check if the repository is alive:
def someDummyFunction(userRepository: UserRepository) = {
if(LivenessChecker.isAlive(userRepository)) // This won't compile
userRepository.findSomeUser()
}
The idea is that our application uses the UserRepository trait and not the implementation, and thus we cannot check whether the repository is alive or not. How can we continue using the repository abstraction layer and be able to check if a given (abstract) repository is alive? Is the typeclass pattern the correct pattern to use here?
There is something a bit fishy with isHealthCheckable inside UserRespository. The isHealthy method, when called, would have two instances of UserRepository available: of course, the one passed as the t argument, but also, the UserRepository.this of the enclosing instance.
This is a sign of something wrong. Either the method should be written somewhere else, so that it does not get enclosing this, or it should not get the argument
That second option is consistent with using UserRepository the object-oriented, subtyping way. Also, it is consistent with your idea that every UserRepository must be heath-checkable. Just do
trait UserRepository {
...
def isHealty: Boolean
}
It is fine to call that directly, userDirectory.isHealthy. But you can then also easily implement the type class:
object UserRepository {
implicit val canHealthCheck = new CanHealthCheck[UserRepository] {
def isHealthy(repository: UserRepository) = repository.IsHealthy
}
}
also note that it was not clear at all how the implicit instance method would have come into the implicit scope. With the companion object, it works fine.
Use "type bounds".
I couldn't test this, but to get the code to compile, you could do something like:
class DbUserRepository[U <: UserRepository] extends UserRepository {
def ping: Boolean = ???
implicit val isHealthCheckable: CanHealthCheck[U] =
new CanHealthCheck[U] {
def isHealthy(db: U) = db.ping
}
}
I'm having trouble finding an elegant way of designing a some simple classes to represent HTTP messages in Scala.
Say I have something like this:
abstract class HttpMessage(headers: List[String]) {
def addHeader(header: String) = ???
}
class HttpRequest(path: String, headers: List[String])
extends HttpMessage(headers)
new HttpRequest("/", List("foo")).addHeader("bar")
How can I make the addHeader method return a copy of itself with the new header added? (and keep the current value of path as well)
Thanks,
Rob.
It is annoying but the solution to implement your required pattern is not trivial.
The first point to notice is that if you want to preserve your subclass type, you need to add a type parameter. Without this, you are not able to specify an unknown return type in HttpMessage
abstract class HttpMessage(headers: List[String]) {
type X <: HttpMessage
def addHeader(header: String):X
}
Then you can implement the method in your concrete subclasses where you will have to specify the value of X:
class HttpRequest(path: String, headers: List[String])
extends HttpMessage(headers){
type X = HttpRequest
def addHeader(header: String):HttpRequest = new HttpRequest(path, headers :+header)
}
A better, more scalable solution is to use implicit for the purpose.
trait HeaderAdder[T<:HttpMessage]{
def addHeader(httpMessage:T, header:String):T
}
and now you can define your method on the HttpMessage class like the following:
abstract class HttpMessage(headers: List[String]) {
type X <: HttpMessage
def addHeader(header: String)(implicit headerAdder:HeaderAdder[X]):X = headerAdder.add(this,header) }
}
This latest approach is based on the typeclass concept and scales much better than inheritance. The idea is that you are not forced to have a valid HeaderAdder[T] for every T in your hierarchy, and if you try to call the method on a class for which no implicit is available in scope, you will get a compile time error.
This is great, because it prevents you to have to implement addHeader = sys.error("This is not supported")
for certain classes in the hierarchy when it becomes "dirty" or to refactor it to avoid it becomes "dirty".
The best way to manage implicit is to put them in a trait like the following:
trait HeaderAdders {
implicit val httpRequestHeaderAdder:HeaderAdder[HttpRequest] = new HeaderAdder[HttpRequest] { ... }
implicit val httpRequestHeaderAdder:HeaderAdder[HttpWhat] = new HeaderAdder[HttpWhat] { ... }
}
and then you provide also an object, in case user can't mix it (for example if you have frameworks that investigate through reflection properties of the object, you don't want extra properties to be added to your current instance) (http://www.artima.com/scalazine/articles/selfless_trait_pattern.html)
object HeaderAdders extends HeaderAdders
So for example you can write things such as
// mixing example
class MyTest extends HeaderAdders // who cares about having two extra value in the object
// import example
import HeaderAdders._
class MyDomainClass // implicits are in scope, but not mixed inside MyDomainClass, so reflection from Hiberante will still work correctly
By the way, this design problem is the same of Scala collections, with the only difference that your HttpMessage is TraversableLike. Have a look to this question Calling map on a parallel collection via a reference to an ancestor type