how to test Akka Action with expectMsgClass - scala

I am new to scala akka
in my test code I have this
val sendEmailActor = system.actorOf(SendEmailActor.props)
sendEmailActor ! email
expectMsgClass(SendEmailActor.SendEmailResult.getClass)
but I got test fail.
java.lang.AssertionError: assertion failed:
expected class vndirect.elasticemail.actor.SendEmailActor$SendEmailResult$,
found class vndirect.elasticemail.actor.SendEmailActor$SendEmailResult
So my SendEmailActor return a SendEmailResult as expected. But the test unit fail. I don't know why. What is difference between SendEmailActor$SendEmailResult$ and SendEmailActor$SendEmailResult

You probably have something like
object SendEmailActor {
...
case class SendEmailResult(some arguments)
object SendEmailResult // may be compiler generated
}
class SendEmailActor {
// has ... ! SendEmailResult(...) in some method
}
SendEmailActor.SendEmailResult.getClass is the class of object SendEmailResult. The class of class SendEmailResult is classOf[SendEmailActor.SendEmailResult], so that's the one you should expect.

I came to this question with a similar problem but the suggested answer didn't work. My task was to check for the arrival of a simple case class used as an Akka message.
The solution was to use:
expectMsgType[Message]
instead of expectMsgClass. (Note "Type" instead of "Class".)

Related

Why is #SerializedName not serializing fields when using Scala (works fine without annotation)

I have the following Code
case class BaseObject(
...
dnsRecord: Array[DNSEntry],
#SerializedName("dnsRecord") dnsEntries: Array[DNSEntry]
)
When I run serialization the dnsRecord works fine whereas the dnsEntries is null...
Update
#fluffy reminded me of another question I saw a while back so I changed things to
case class BaseObject(
...
dnsRecord: Array[DNSEntry],
#(SerializedName#scala.annotation.meta.field)("dnsRecord") dnsEntries: Array[DNSEntry]
)
This threw an issue because it tried to use the dnsRecord field which was already used.
The answer looked like this...
case class BaseObject(
...
#(SerializedName#scala.annotation.meta.field)("dnsRecord") dnsEntries: Array[DNSEntry]
)
or even better
object GsonScala {
type SerializedName = com.google.gson.annotations.SerializedName #scala.annotation.meta.field
}
case class BaseObject(
...
#GsonScala.SerializedName("dnsRecord") dnsEntries: Array[DNSEntry]
)

Wicket NumberTextField in Kotlin throws ClassCastException when submitted

I'm having some issues with a Wicket (8.0.0-M4) NumberTextField in Kotlin (1.1.0).
My stripped-down form looks like this:
class Test : AbstractWebPage() {
val housenumberModel: Model<Int> = Model<Int>()
val housenumber = NumberTextField<Int>("housenumberModel", housenumberModel)
val form: Form<Unit> = object : Form<Unit>("adressForm") {}
override fun onInitialize() {
super.onInitialize()
form.add(housenumber.setRequired(false))
form.add(object : SubmitLink("submit") {
override fun onSubmit() {
super.onSubmit()
println(housenumberModel.`object`) // this is line 28
}
})
add(form)
}
}
After submitting the form I get the following stacktrace:
java.lang.ClassCastException: java.lang.String cannot be cast to
java.lang.Number
at com.mycompany.test.pages.Test$onInitialize$1.onSubmit(Test.kt:28)
at org.apache.wicket.markup.html.form.Form.delegateSubmit(Form.java:1312)
at org.apache.wicket.markup.html.form.Form.process(Form.java:979)
at org.apache.wicket.markup.html.form.Form.onFormSubmitted(Form.java:802)
at org.apache.wicket.markup.html.form.Form.onRequest(Form.java:715)
at org.apache.wicket.core.request.handler.ListenerRequestHandler.internalInvoke(ListenerRequestHandler.java:301)
at org.apache.wicket.core.request.handler.ListenerRequestHandler.invoke(ListenerRequestHandler.java:250)
at org.apache.wicket.core.request.handler.ListenerRequestHandler.invokeListener(ListenerRequestHandler.java:210)
at org.apache.wicket.core.request.handler.ListenerRequestHandler.respond(ListenerRequestHandler.java:203)
at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:912)
at org.apache.wicket.request.RequestHandlerExecutor.execute(RequestHandlerExecutor.java:65)
at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:283)
at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:253)
at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:221)
at org.apache.wicket.protocol.http.WicketFilter.processRequestCycle(WicketFilter.java:262)
at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:204)
at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:286)
[...]
If I use
val housenumberModel: Model<Int> = Model.of(0)
instead of
val housenumberModel: Model<Int> = Model<Int>()
everything works fine. But since my NumberTextField is optional I don't want to have it pre-initialized with 0.
Me and my colleagues were trying to change the type signature of the Model in every way we could imagine but came to no solution. A co-worker suggested to write a custom Wicket converter since Kotlins Int is represendeted as a primitive type (From the docs: "On the JVM, non-nullable values of this type are represented as values of the primitive type int.") Even though I don't know yet if this would work it seems like an overkill for me.
Another hack I could think of: writing some JavaScript to delete the zero from the input field. Also not really something I would want to do.
Question: Is there a simple solution to my problem?
(And as a bonus-question: has already anyone written a larger Wicket application in Kotlin and could tell me if this combination is ready for prime time to develop a critical project with this stack or is my problem just the tip of the iceberg?)
[edit]
Solution as pointed out by svenmeier:
Using
val housenumber = NumberTextField<Int>("housenumberModel", housenumberModel, Int::class.java)
works.
Or as an alternative:
val housenumbervalue: Int? = null
val housenumberModel: IModel<Int> = PropertyModel<Int>(this, "housenumbervalue")
val housenumber = NumberTextField<Int>("housenumberModel", housenumberModel)
Because of type erasure your NumberTextField cannot detect the generic type parameter of your model. Since your model object is null, it cannot be used to derive the type either.
In this case Wicket assumes a String model object type :/.
Either provide the type to the NumberTextField explicitly, or use a model that keeps its generic information, e.g. a PropertyModel.
There is a way to tell wicket about the type you want, it is by adding the type in the constructor. More here.
In Java it looks like this:
new NumberTextField<Integer>("housenumberModel", housenumberModel, Integer.class);

Screenshot on every failure using Scalatest

I would like to take a screenshot on every fail test in a Spec or Suite using ScalaTest.
The Scala Test website shows how to take screenshots surrounding every code that might fail with this:
withScreenshot {
drive.findElement(By.id("login")).getAttribute("value") should be ("Login")
}
There is this post that tries to explain, but I could not understand what exactly should be done.
I also found the class ScreenshotOnFailure.scala, but could not use it, once it's private and has a package restriction.
Can anyone tell me if there's a way to intercept any failure and then take a screenshot?
Just to have a final answer I'm writing the way I could solve the problem based on the approach from this post mentioned in the question.
In short, the solution ended up like this (pseudo-code).
trait Screenshots extends FunSpec {
...
override def withFixture(test: NoArgTest): Outcome = {
val outcome = test()
// If the test fails, it will hold an exception.
// You can get the message with outcome.asInstanceOf[Failure].exception
if (outcome.isExceptional) {
// Implement Selenium code to save the image using a random name
// Check: https://stackoverflow.com/questions/3422262/take-a-screenshot-with-selenium-webdriver
}
outcome
}
}
class MySpec extends Screenshots {
...
describe("Scenario A") {
describe("when this") {
it("the field must have value 'A'") {
// It will save a screenshot either if the selector is wrong or the assertion fails
driver.findElement(By.id("elementA")).getAttribute("value") should be ("A")
}
}
}
}
From this point on, all Specs that extend the Screenshot trait will intercept errors and save a screenshot.
Just to complement, surrounding areas with withScreenshot(), as mentioned in the question, saves only failure on assertions, but it does not save a screenshot when the test fails due an element not found (e.g. wrong selector).
With the code above, all failures will save a screenshot.

Scala - unbound wildcard exception (Play Framework 2.3 Template)

I am using Play Framework 2.3 I am using the scala template engine to create my views and Java elsewhere.
My model extends an abstract parameterised object like so... (pseudo code)
Abstract object:
public abstract class MyObject<T> {
// various bits
public class MyInnerObject {
// more stuff
}
}
Model object (singleton)
public class SomeModel extends MyObject<SomeBean> {
public static SomeModel getInstance() {
if (instance == null)
instance = new SomeModel();
return instance;
}
// more bits
}
I then pass the model to the view from another view helper:
#MyHelper(SomeModel.getInstance())
MyHelper scala view template:
#*******************************************
* My helper
*******************************************#
#(myObj: some.namespace.MyObject[_])
#import some.namespace.MyObject
#doSomething(myInnerObj: MyObject[_]#MyInnerObject) = {
#* do some stuff *#
}
#for(myInnerObj <- myObj.getInnerObjects()) {
#doSomething(myInnerObj)
}
However I get an error on the line #doSomething(myInnerObj: MyObject[_]#MyInnerObject) stating
unbound wildcard exception
I am not sure the correct Scala syntax to avoid this error I had naively assumed that I could use the _ to specify arbitrary tyope but it won't let me do this.
What is the correct syntax?
UPDATE 1
Changing the method definition to:
#doSomething[T](myInnerObj: MyObject[T]#MyInnerObject)
gives further errors:
no type parameters for method doSomething: (myInnerObj:[T]#MyInnerObject)play.twirl.api.HtmlFormat.Appendable exist so that it can be applied to arguments (myObj.MyInnerObject)
--- because ---
argument expression's type is not compatible with formal parameter type;
found : myObj.MyInnerObject
required: MyObject[?T]#MyInnerObject
It would seem that the Twirl templating engine does not support this syntax currently, although I'm not 100% sure.
I can solve the problem by removing the doSomething method completely...
#*******************************************
* My helper
*******************************************#
#(myObj: some.namespace.MyObject[_])
#import some.namespace.MyObject
#for(myInnerObj <- myObj.getInnerObjects()) {
<div>#myInnerObj.getSomeProperty()</div>
}
But I am bout 10% happy with the solution... It works at least but it feels very restricting that I cannot delegate to methods to help keep my code maintainable. By the look of the comments the problem seems to be a limitation in Twirl, not allowing type arguments for functions in views.
Note: I have accepted this answer as it removes the original problem of the exception however this is only because the solution I want doesn't exist... yet.

Scala problem with jMock expectations and returning a value from mock

Solved. IntelliJ didn't highlight the fact that my imports were incomplete.
Hi,
I have a simple Scala program that I'm trying to develop using jMock. Setting basic expectations works nicely but for some reason Scala does not understand my attempt to return a value from a mock object. My maven build spews out the following error
TestLocalCollector.scala:45: error: not found: value returnValue
one (nodeCtx).getParameter("FilenameRegex"); will( returnValue(regex))
^
And the respective code snippets are
#Before def setUp() : Unit = { nodeCtx = context.mock(classOf[NodeContext]) }
...
// the value to be returned
val regex = ".*\\.data"
...
// setting the expectations
one (nodeCtx).getParameter("FilenameRegex"); will( returnValue(regex))
To me it sounds that Scala is expecting that the static jMock method returnValue would be a val? What am I missing here?
Are you sure about the ';'?
one (nodeCtx).getParameter("FilenameRegex") will( returnValue(regex))
might work better.
In this example you see a line like:
expect {
one(blogger).todayPosts will returnValue(List(Post("...")))
}
with the following comment:
Specify what the return value should be in the same expression by defining "will" as Scala infix operator.
In the Java equivalent we would have to make a separate method call (which our favorite IDE may insist on putting on the next line!)
one(blogger).todayPosts; will(returnValue(List(Post("..."))))
^
|
-- semicolon only in the *Java* version
The OP explains it himself:
the returnValue static method was not visible, thus the errors.
And the will method just records an action on the latest mock operation, that's why it can be on the next line or after the semicolon :)
import org.jmock.Expectations
import org.jmock.Expectations._
...
context.checking(
new Expectations {
{ oneOf (nodeCtx).getParameter("FilenameRegex") will( returnValue(".*\\.data") ) }
}
)