I'm working on a scala object in order to perform some testing
My start object is as follows
object obj1 {
def readvalue : IO[Float] = IO{
scala.io.StdIn.readFloat()
}
}
The testing should be
1- value of type FLOAT
2- should be less than 3
As we can not mock singleton objects I've used mocking functions here is what I've done.
class FileUtilitiesSpec
extends FlatSpec
with Matchers
with MockFactory
{
"value" should "be of Type Float" in {
val alpha = mockFunction[() => IO[Float]]
alpha.expects shouldBe a[IO[Float]]
}
"it" should "be less than 3" in {
val alpha = mockFunction[() => IO[Float]]
alpha.expects shouldBe <(3)
}
}
Im getting an error saying that :
MockFunction0-1() once (never called - UNSATISFIED) was not an instance of cats.effect.IO, but an instance of org.scalamock.handlers.CallHandler0
ScalaTestFailureLocation: util.FileUtilitiesSpec at (FileUtilitiesSpec.scala:16)
Expected :cats.effect.IO
Actual :org.scalamock.handlers.CallHandler0 ```
I would recommend reading the examples here as a starting point: https://scalamock.org/quick-start/
Using mock objects only makes sense if you are planning to use them in some other code, e.g. dependencies you do not want to make part of your module under test, or are beyond your control.
An example might be a database connection where you would depend on an actual system, making the code hard to test without simulating it.
The example you provided only has mocks, but no code using it, hence the error you are getting is absolutely correct. The mock expects to be used, but was not called.
The desired behaviour for a mocking library in this case is to make the test fail as the developer intended for this interaction with a mock to happen, but it was not recorded - so something is wrong.
Related
Consider following snippet; I have used WSClient here for some api calls via DI.
#Singleton
class SampleService #Inject()(ws: WSClient) {
def get(id:Long): JsValue ={
val trailingURL = s"/$id".toString
val wsRequest = ws.url(baseURL+trailingURL).addQueryStringParameters("access_token" -> authToken).get()
val wsResponse = Await.result(wsRequest, Duration.Inf)
Json.toJson(wsResponse.body)
}
}
And I need to write unit test for get method. I'm doing the following thing
val mockedWS = mock[WSClient]
val sparrowService = new SurveySparrowService(mockedWS)
"get method" should {
"return a valid result with valid id" in {
val result = sparrowService.get(66405)
println(result)
assert(result.toString == `the result i'll get`)
}
}
But the mocking fails and i get a null pointer exception in following line=>
val wsRequest = ws.url(baseURL+trailingURL).addQueryStringParameters("access_token" -> authToken).get()
Also when i'm using Json.toJson(wsResponse.body) i'm getting extra \ with each parameter in whole response.
can anyone help me solving these two problems. Thanks.
There is play-mockws, which exists solely because mocking a WSClient manually is really tedious.
// simulation of a GET request to http://dns/url
val ws = MockWS {
case (GET, "http://dns/url") => Action { Ok("http response") }
}
await(ws.url("http://dns/url").get()).body == "http response"
Further explanation:
Mocking a class / trait simply creates you an instance of that type out of thin air. You cannot do anything with that instance in general, calling any method on it will simply return null. If your code under test calls methods of this object, you must stub those methods with answers (i.e. simply return a prepared value).
For WSClient, this means you must stub the url method since this will be called by any code doing HTTP requests. But this method returns a WSRequest. So, you must mock this also... Any call on this new mock needs to be stubbed too, or else it will end in a NPE again. This really gets complicated very soon, and you probably don't understand your test code too well anymore. That's why play-mockws was created which makes it very easy to reason about calls to HTTP services in your Play application.
BTW, you may also combine play-mockws with the SIRD - String Interpolation Router DSL, which makes it even easier to extract values out of the routes or query parameters if you need to:
val ws = MockWS {
case GET(p"/$id") if id == "66405" =>
Action {
Results.Ok("...")
}
}
Actually, the main problem is still that there are no reified typeargs for classes in Kotlin. But here is why this bothers me in this specific case:
Suppose you have a wrapper class Wrapper that takes in a string content and a class* type and can output an object of class type retrieved by parsing content as JSON by demand by calling the function getObj():
class Wrapper<T>(private val content: String, /*private val type: KClass<*>*/) {
fun getObj(): T {
// ?
}
}
And I want to use kotlinx.serialization. Now, you might have noticed how I put an asterisk after "class" before. Here's the reason: Yes, Wrapper has to take the target class in some way, but how? Should it be just the typearg (won't work because type erausre) or a KClass reference (won't work because I need a reified typearg)?
The thing is that as far as I know, the only way to decode a generic JSON to a serializable target class is to use Json.decodeFromString<T>(content), where T is the target type and content is the JSON string. Now, T is defined to be reified (so that the type can be processed at runtime) and can only be filled with another reified typearg or an actual class reference. I can't use another reified typearg because I am in the context of a class and a class cannot have reified typeargs. I can also not use an actual class reference because the user of the class should be able to construct it with different targets, e.g. they decide what the target is, not me.
So, how do I do this with kotlinx.serialization? Is it even possible?
Ok so no one answered the question yet, but I also posted this question in the r/Kotlin subreddit. Here it is.
I actually got an answer there (credits to u/JakeWharton), and since you might get across this StackOverflow question because you googled the same question, you might be happy to find an answer here. So here's my try to paraphrase the answer:
So, basically, kotlinx-serialization does indeed not work with KClasses. But when you think about it, you only need the KClass to determine how to serialize it. And since that is determined at compile-time when you work with KXS, you actually just need to pass the serializer (the actual strategy defining how to serialize / deserialize your class). You can obtain a serializer for every class annotated with #Serializable by invoking .serializer() on it; the result will be of the type KSerializer<T>. So, instead of having
class Wrapper<T>(private val content: String, private val type: KClass<T>)
and constructing it via
val wrapper = Wrapper("{}", Foo::class)
You can do it like this:
class Wrapper<T>(private val content: String, private val serializer: KSerializer<T>)
and then construct it like this:
val wrapper = Wrapper("{}", Foo.serializer())
(supposing Foo is annotated with #Serializable)
you can then serialize and deserialize by using the KSerializer instead of a typearg, like this:
val obj: T = Json.decodeFromString(serializer, "[Your JSON String]")
val str: String = Json.encodeToString(serializer, obj)
And that's it! Just swap out your regular (K)Class approach by KSerializer and it'll work with KXS.
I want to send slick table as part of the akka actor message . So that the remote actor at the other end can connect to the database and can do CRUD operations on the mysql database. Am unable to get my head over the slick types and i find compiler/eclipse complaining. How can i get this done. Is it a good idea to pass slick queries as part of actor messages.
object RemoteActorMessages {
case class Create(table: Table[A])
case class RunQuery(query: Query[_, _, _])
case Result(code: Int, message: String)
}
class DBActor extends Actor {
def recieve = {
case Create(table) => createTable(table)
case RunQuery(query) => runQuery(query)
case ... //so on
}
}
def createTable(table: Table[M]): Future[A] = Future {
db.withSession(implicit session => tableQuery[table].ddl.create)
}
def runQuery(query: Query[_, _, _]): Future[A] = Future {
db.withSession { implicit session => {
query.run
}
}
}
warning: code might have some type errors.Discretion is appreciated from the viewers
I am confused about how to send results back to the sender of the messages. for example: query.list.run gives back list of model objects. So, how should i frame by Result message
I think this is a case of 'when you have a hammer everything becomes nails'. I believe this is not the right use case for the actors. A reason (not the only one) would be that DB operations are 'slow' and they would block the actor threads for a long time.
Arguably you want a service that manages the table operations, using Futures and a custom Execution Context to isolate the impact (for example, in Play is done like this). Something like:
object DBService {
def createTable() : Future[Boolean] = ???
...
}
Actors should only receive commands like CreateTable that then call the corresponding method in the service.
Incidentally, this would simplify your use case as the service could know more about the table and other Slick specifics, whilst the actor would be oblivious to them.
Not the only way, but arguably simpler.
I'm trying to learn Scala and the Play Framework at the same time. Scala looks to me like it has a lot of really cool ideas, but one of my frustrations is trying to understand all of the different syntaxes for methods/functions/lambdas/anonymous functions/etc.
So I have my main application controller like so:
object Application extends Controller {
def index = Action {
Ok(views.html.index("Your new application is ready."))
}
}
This tells me I have a singleton Application that has one method, index, that returns what type?? I was expecting index to have a definition more like:
def index(req: Request) : Result = { ... }
Looking at Play Framework's documentation, it looks as though Action is a trait, that transforms a request to a result, by I'm having a hard time understanding what this line is saying:
def index = Action { ... }
I come from a Java background, so I don't know what this is saying? (this statement feels like it's saying "method index = [some interface Action]", which doesn't make sense to me; it seems something beautiful is happening, but it is magic to me, and I feel uneasy with magic in my code ;))
When you invoke an object as if it were a function, that's translated into a call to apply. I.e.:
foo(bar)
is translated into
foo.apply(bar)
So, inside index you are calling the Action object as if it were a function, which means you are actually calling Action.apply.
The return type of index is omitted because the compiler can infer it to be the return type of Action.apply (which I guess from the name is Unit).
So the short answer to this question is that there's some stuff going on behind the scenes that makes the above work: namely that the compiler is inferring types, and in Scala, objects with an apply method can get called as if they were functions.
So what's going on here is that this code:
def index = Action {
Ok("Hello World!")
}
...is equivalent to (or rather shorthand for) this code:
def index : Action[AnyContent] = Action.apply(
(req: Request[AnyContent]) => {
Ok(views.html.index("Hello World!"))
} : Result
)
The magic is happening here: ... = Action {...}. Action {...} says "call Action with this anonymous function {...}".
Because Action.apply is defined as apply(block: => Result): Action[AnyContent], all of the argument-/return- types can be inferred.
What do i need to do to extract the value for friends_count. i noticed that screen_name are already define in the Status object and case class. Do still require to extends Js or JsObject different
object TweetDetails extends Js { val friends_count = 'friends_count ? num }
and then pattern match it against each json object in the list of JsObjects as represented below. The symbols are confusing:
scala> val friends_count = 'friends_count ! num // I wish SO understood Scala's symbols
val twtJsonList = http(Status("username").timeline)
twtJsonList foreach {
js =>
val Status.user.screen_name(screen_name) = js
val Status.text(text) = js
val friends_counts(friends_count) = js //i cannot figure out how to extract this
println(friends_count)
println(screen_name)
println(text)
}
Normally, Scala symbols can be thought of as a unique identifier which will always be the same. Every symbol that is lexi-graphically identical refers to the exact same memory space. There's nothing else that's special about them from Scala's point of view.
However, Dispatch-Json pimps out symbols making them JSON property extractors. To see the code which is responsible for the pimping, check out the SymOp class and the rest of the JsonExtractor.scala code.
Let's write some code which solves the problem you are looking at and then analyze what's going on:
trait ExtUserProps extends UserProps with Js {
val friends_count = 'friends_count ! num
}
object ExtUser extends ExtUserProps with Js
val good_stuff = for {
item <- http(Status("username").timeline)
msg = Status.text(item)
user = Status.user(item)
screen_name = ExtUser.screen_name(user)
friend_count = ExtUser.friends_count(user)
} yield (screen_name, msg, friend_count)
The first thing that we're doing is extending the UserProps trait in the Dispatch-Twitter module to give it a friends_count extractor and then defining a ExtUser object which we can use to get access to that extractor. Because the ExtUserProps extends UserProps, which also extends Js, we get the method sym_add_operators in scope which turns our symbol 'friends_count into a SymOp case class. We then call the ! method on that SymOp which we then pass the Extractor num to, which creates an Extractor that looks for a property "friends_count" on a JSON object and then parses it as a number before returning. Quite a bit going on there for such a small bit of code.
The next part of the program is just a for-comprehension that calls out to the Twitter timeline for a user and parses it into JsObjects which represent each status item, them we apply the Status.text extractor to pull out the status message. Then we do the same to pull out the user. We then pull the screen_name and friend_count out of the user JsObject and finally we yield a Tuple3 back with all of the properties we were looking for. We're then left with a List[Tuple3[String,String,BigDecimal]] which you could then iterate on to print out or do whatever with.
I hope that clears some things up. The Dispatch library is very expressive but can be a little tough to wrap your head around as it uses a lot of Scala tricks which someone just learning Scala won't get right away. But keep plugging around and playing with, as well as looking at the tests and source code, and you'll see how to create powerful DSL's using Scala.