Checking if a Scala List is of class List [duplicate] - scala

I'm trying to incorporate ScalaTest into my Java project; replacing all JUnit tests with ScalaTests. At one point, I want to check if Guice's Injector injects the correct type. In Java, I have a test like this:
public class InjectorBehaviour {
#Test
public void shouldInjectCorrectTypes() {
Injector injector = Guice.createInjector(new ModuleImpl());
House house = injector.getInstance(House.class);
assertTrue(house.door() instanceof WoodenDoor);
assertTrue(house.window() instanceof BambooWindow);
assertTrue(house.roof() instanceof SlateRoof);
}
}
But I have a problem doing the same with ScalaTest:
class InjectorSpec extends Spec {
describe("An injector") {
it("should inject the correct types") {
val injector = Guice.createInjector(new ModuleImpl)
val house = injector.getInstance(classOf[House])
assert(house.door instanceof WoodenDoor)
assert(house.window instanceof BambooWindow)
assert(house.roof instanceof SlateRoof)
}
}
}
It complains that the value instanceof is not a member of Door/Window/Roof. Can't I use instanceof that way in Scala?

Scala is not Java. Scala just does not have the operator instanceof instead it has a parametric method called isInstanceOf[Type].
You might also enjoy watching a ScalaTest Crash Course.

With Scalatest 2.2.x (maybe even earlier) you can use:
anInstance mustBe a[SomeClass]

If you want to be less JUnit-esque and if you want to use ScalaTest's matchers, you can write your own property matcher that matches for type (bar type erasure).
I found this thread to be quite useful: http://groups.google.com/group/scalatest-users/browse_thread/thread/52b75133a5c70786/1440504527566dea?#1440504527566dea
You can then write assertions like:
house.door should be (anInstanceOf[WoodenDoor])
instead of
assert(house.door instanceof WoodenDoor)

The current answers about isInstanceOf[Type] and junit advice are good but I want to add one thing (for people who got to this page in a non-junit-related capacity). In many cases scala pattern matching will suit your needs. I would recommend it in those cases because it gives you the typecasting for free and leaves less room for error.
Example:
OuterType foo = blah
foo match {
case subFoo : SubType => {
subFoo.thingSubTypeDoes // no need to cast, use match variable
}
case subFoo => {
// fallthrough code
}
}

Consolidating Guillaume's ScalaTest discussion reference (and another discussion linked to by James Moore) into two methods, updated for ScalaTest 2.x and Scala 2.10 (to use ClassTag rather than manifest):
import org.scalatest.matchers._
import scala.reflect._
def ofType[T:ClassTag] = BeMatcher { obj: Any =>
val cls = classTag[T].runtimeClass
MatchResult(
obj.getClass == cls,
obj.toString + " was not an instance of " + cls.toString,
obj.toString + " was an instance of " + cls.toString
)
}
def anInstanceOf[T:ClassTag] = BeMatcher { obj: Any =>
val cls = classTag[T].runtimeClass
MatchResult(
cls.isAssignableFrom(obj.getClass),
obj.getClass.toString + " was not assignable from " + cls.toString,
obj.getClass.toString + " was assignable from " + cls.toString
)
}

I use 2.11.8 to do the assertion with collections. The newer syntax is as follows:
val scores: Map[String, Int] = Map("Alice" -> 10, "Bob" -> 3, "Cindy" -> 8)
scores shouldBe a[Map[_, _]]

Related

Or operator with scalaTest matcher

Using scalatest idiomatic matcher how can I check if a class is instance of A or B?
I try with or but it does not work
e shouldBe a [ChannelWriteException] || e shouldBe a [ConnectException]
Here How to do an instanceof check with Scala(Test) explain how to use isInstanceOf, but not how to make an or
Regards.
you can use Matcher#should(Matcher[T]) with Matcher#or[U <: T](Matcher[U])
example,
it("test instanceOf A or B") {
val actual = new Thread()
actual should (be (a [RuntimeException]) or be (a [Thread]))
}
if actual does not match the expected, it errors out with proper messaging,
it("test instanceOf A or B") {
val actual = new String()
actual should (be (a [RuntimeException]) or be (a [Thread]))
}
error
"" was not an instance of java.lang.RuntimeException, but an instance of java.lang.String, and
"" was not an instance of java.lang.Thread, but an instance of java.lang.String
The conventional way, (I'm still in 2000s)
val actual = new Thread()
assert(actual.isInstanceOf[RuntimeException] || actual.isInstanceOf[Thread])
Reference
http://www.scalatest.org/user_guide/using_matchers#logicalExpressions
Is there anyway we can give two conditions in Scalatest using ShouldMatchers

AspectJ can't work on Scala function literal?

I have the following scala class and annotated aspectj class:
package playasjectj
import org.aspectj.lang.annotation.Pointcut
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.Before
class Entity {
def foo(p:String):String ={
return p
}
def bar(handler:(String,String,Long)=>String):Unit={
handler("first", "second", 100L)
}
}
object Entity {
def main(args:Array[String]){
val inst = new Entity
inst.foo("we are the champion")
val handler = (first:String, second:String, value:Long) => {
first + second + ":" + value
}
inst.bar(handler)
}
}
#Aspect
class EntityAspect{
#Pointcut("execution(* foo(String) ) && target(playasjectj.Entity) && args(p)")
def pointcut_foo(p:String):Unit={}
#Pointcut("execution(* bar(scala.Function3<String,String,Long,String>)) && target(playasjectj.Entity) && args(handler)")
def pointcut_bar(handler: (String,String,Long)=>String):Unit={}
#Before("pointcut_foo(p)")
def beforeAdvice_foo(p:String):Unit={
println("before advice foo: " + p)
}
#Before("pointcut_bar(handler)")
def beforeAdvice_bar(handler:(String,String,Long)=>String):Unit={
println("before advice bar:")
}
}
function bar works well, but function foo doesn't. There is no any errors, seems the execution of function "foo" is not caught.
[AppClassLoader#14dad5dc] info AspectJ Weaver Version 1.8.5 built on Thursday Jan 29, 2015 at 01:03:58 GMT
[AppClassLoader#14dad5dc] info register classloader sun.misc.Launcher$AppClassLoader#14dad5dc
[AppClassLoader#14dad5dc] info using configuration /Users/grant/programming/java/workspace/playasjectj/bin/META-INF/aop.xml
[AppClassLoader#14dad5dc] info register aspect playasjectj.EntityAspect
before advice foo: we are the champion
Anyone knows how to solve the problem? I guess it is related to how scala transform the tuple into java class
solved by myself. the problem is not function literal, but type "Long". If I use "java.lang.Long" in that situation, that works. for generic type, AspectJ expects "Type",not primitive. in Scala, numeric type values like Int, Long, even Boolean are equivalent to java primitive type

how to reflect scala trait class field, use getDeclaredFields but got nothing?

var cl: URLClassLoader = _
var out: TaskStreams = _
var clazz = cl.loadClass("io.marsdigtal.XXX.UserTrait")
if (clazz.isInterface) {
clazz = cl.loadClass(className + "$class")
clazz.getDeclaredFields.foreach { each =>
out.log.info("fieldName: " + each.getName)
}
}
so I use getDeclaredFields, but got nothing...
how can I reflect trait fiedld by scala or java reflection?
This doesn't solve your problem specifically but if someone wants to get a list of fields on a known trait:
new SomeTrait{...}.getClass.getDeclaredFields
I was using this to list fields in a trait hierarchy in dependency / declared order.
[EDIT] There is a caveat. The fields can't be used for 'get'. Obtain the real field on the class instance in question before calling 'get':
val real = cls.getDeclaredField(f.getName)
real.setAccessible(true)
real.get(someInst)

What is this Scala 'new' syntax

From the ScalaTest docs:
class ExampleSpec extends FlatSpec {
def fixture =
new {
val builder = new StringBuilder("ScalaTest is ")
val buffer = new ListBuffer[String]
}
...
I don't understand how the new keyword is being used here. fixture is obviously a function, which declares and returns... what? It seems to be an object, since it has members (builder & buffer) that can be accessed with . notation.
Is what is being created here an anonymous class that is a subclass of AnyRef?
Yep, it returns instance of anynomous class. It is not hard to check it by yourself in REPL session:
scala> def fixture = new { val string = "mr. String" }
fixture: Object{val string: String}
Java can do the essentially same thing, believe it or not. The following is valid Java
(new Object() {
public void sayHello() {
System.out.println("hello!");
}
}).sayHello();
The Java version is just a mildly more verbose syntax and has a type system limitation that makes it mostly useless.
More about it here http://james-iry.blogspot.com/2009/04/java-has-type-inference-and-refinement.html

Syntactic sugar for compile-time object creation in Scala

Lets say I have
trait fooTrait[T] {
def fooFn(x: T, y: T) : T
}
I want to enable users to quickly declare new instances of fooTrait with their own defined bodies for fooFn. Ideally, I'd want something like
val myFoo : fooTrait[T] = newFoo((x:T, y:T) => x+y)
to work. However, I can't just do
def newFoo[T](f: (x:T, y:T) => T) = new fooTrait[T] { def fooFn(x:T, y:T):T = f(x,y); }
because this uses closures, and so results in different objects when the program is run multiple times. What I really need is to be able to get the classOf of the object returned by newFoo and then have that be constructable on a different machine. What do I do?
If you're interested in the use case, I'm trying to write a Scala wrapper for Hadoop that allows you to execute
IO("Data") --> ((x: Int, y: Int) => (x, x+y)) --> IO("Out")
The thing in the middle needs to be turned into a class that implements a particular interface and can then be instantiated on different machines (executing the same jar file) from just the class name.
Note that Scala does the right thing with the syntactic sugar that converts (x:Int) => x+5 to an instance of Function1. My question is whether I can replicate this without hacking the Scala internals. If this was lisp (as I'm used to), this would be a trivial compile-time macro ... :sniff:
Here's a version that matches the syntax of what you list in the question and serializes/executes the anon-function. Note that this serializes the state of the Function2 object so that the serialized version can be restored on another machine. Just the classname is insufficient, as illustrated below the solution.
You should make your own encode/decode function, if even to just include your own Base64 implementation (not to rely on Sun's Hotspot).
object SHadoopImports {
import java.io._
implicit def functionToFooString[T](f:(T,T)=>T) = {
val baos = new ByteArrayOutputStream()
val oo = new ObjectOutputStream(baos)
oo.writeObject(f)
new sun.misc.BASE64Encoder().encode(baos.toByteArray())
}
implicit def stringToFun(s: String) = {
val decoder = new sun.misc.BASE64Decoder();
val bais = new ByteArrayInputStream(decoder.decodeBuffer(s))
val oi = new ObjectInputStream(bais)
val f = oi.readObject()
new {
def fun[T](x:T, y:T): T = f.asInstanceOf[Function2[T,T,T]](x,y)
}
}
}
// I don't really know what this is supposed to do
// just supporting the given syntax
case class IO(src: String) {
import SHadoopImports._
def -->(s: String) = new {
def -->(to: IO) = {
val IO(snk) = to
println("From: " + src)
println("Applying (4,5): " + s.fun(4,5))
println("To: " + snk)
}
}
}
object App extends Application {
import SHadoopImports._
IO("MySource") --> ((x:Int,y:Int)=>x+y) --> IO("MySink")
println
IO("Here") --> ((x:Int,y:Int)=>x*y+y) --> IO("There")
}
/*
From: MySource
Applying (4,5): 9
To: MySink
From: Here
Applying (4,5): 25
To: There
*/
To convince yourself that the classname is insufficient to use the function on another machine, consider the code below which creates 100 different functions. Count the classes on the filesystem and compare.
object App extends Application {
import SHadoopImports._
for (i <- 1 to 100) {
IO(i + ": source") --> ((x:Int,y:Int)=>(x*i)+y) --> IO("sink")
}
}
Quick suggestion: why don't you try to create an implicit def transforming FunctionN object to the trait expected by the --> method.
I do hope you won't have to use any macro for this!