I'm new to writing junit tests in Scala and I'm using Mockito to mock objects. I'm also using scalatest_2.12-3.0.4. The ScalaTest documentation (like here) shows the syntax to create the mock using MockitoSugar, i.e.
val mockCollaborator = mock[Collaborator]
Eclipse shows org.scalatest.mock.MockitoSugar crossed out in the import statement, indicating it is deprecated. The only alternative I've found is, don't use MockitoSugar and instead do:
val mockCollaborator = mock(classOf[Collaborator])
This seems to work fine too, so I'm curious what ScalaTest is recommending me to use.
Or for that matter, why else would I use MockitoSugar? Does it have any other features? I've been unable to find any documentation about it, except that everybody seems to use the shorthand mock[] notation.
Base on the issue and some comments, the answer should be changed:
the MockitoSugar has been moved to a separate project: https://github.com/scalatest/scalatestplus-mockito
need to add a new dependency to use it
https://mvnrepository.com/artifact/org.scalatestplus/mockito-3-4_2.13/3.3.0.0-SNAP3
testCompile group: 'org.scalatestplus', name: 'mockito-3-4_2.13', version: '3.3.0.0-SNAP3'
origin issue: https://github.com/scalatest/scalatest/issues/1789
As reported in the source you should use org.scalatest.mockito.MockitoSugar instead of org.scalatest.mock.MockitoSugar
Related
I have a package object defined in both main and the test code tree as shown below. When I execute the program with sbt run the one in the main code tree takes effect. Whereas when I run the test cases (sbt test) the package object defined in the test code tree takes effect. For eg
src/main/scala/com/example/package.scala
package object core {
val foo = "Hello World"
}
src/test/scala/com/example/package.scala
package object core {
val foo = "Goodbye World"
}
on sbt run the value of com.example.core.foo is Hello World. on sbt test the value of com.example.core.foo is Goodbye World
Is this just a quirk of SBT or is it a well defined scala/sbt trait?. I currently use this behaviour for dependency injection by defining my module bindings for production and test in their corresponding package objects. This is an advisable approach?
Scala looks for package objects in your current path, so it's a well defined behavior. Since your code in test and main resides in different places it finds different val foos.
The way you are using this mechanism is very similar to using implicits. General advice with implicits and implicit resolution is not to abuse it. I think in this case it's not the best way of providing dependencies.
You always have to consider what scope you are in - if you are using a class defined in main in test scope how do you use foo from main, and how do you use foo from test - whenever you need one or the other. You have to think already about how it will work and consider various scenarios. What if your test class is in a different package, which foo would you get, does it depend on where your tested class is declared?
Make dependency injection more explicit and don't spend mental cycles on it, or run a chance to get someone confused.
I noticed that Monocle has implementations of lens laws that are used to test the libraries internals. They seem to be nicely generalized and modularized. I tried to use them to test my own lenses, but I am lost in the jungle of dependencies. Has anybody tried to do this, and could post an example? The documentation does not seem to talk about laws at all. Thank you.
To elaborate, here is what I am trying to do (fumbling, not sure if I am using the intended way to use the API):
it should "pass the LensLaws" in check {
forAll {(c: (String,Int), a: String) =>
new monocle.law.LensLaws(l).setGet(c,a) } }
where l is the Monocle lens, visible in scope. I am receiving the following error message:
No implicit view available from monocle.internal.IsEq[String] => org.scalacheck.Prop
As far as I can see the setGet law constructs an IsEq object and I was not able to find how to turn it into a Prop (or Boolean).
I can also see that the framework is using a function checkAll to test all LensLaws at the same time, but I could not get this to work in my own code either. Any help appreciated.
The following works for me
import org.scalatest.FunSuite
import org.typelevel.discipline.scalatest.Discipline
class LensesSuite extends FunSuite with Discipline {
import scalaz._
import Scalaz._
checkAll("Lens l", monocle.law.discipline.LensTests(l))
}
It turns out that the main problem was my relatively short knowledge on scalatest. checkAll is a checker provided by org.typelevel.discipline.scalatest.Discipline, which only works in FunSuite (not in FlatSpec that I was using). It took me ages to figure that out ...
Still have no idea how to elegantly use this RuleSet (LensTests) into another spec. It seems strange that the choice of RuleSet by Monocle would enforce the Spec style on the project using these tests.
Assume you have two SBT projects, one called A and another called B
A has a subproject called macro, that follows the exact same pattern as showed here (http://www.scala-sbt.org/0.13.0/docs/Detailed-Topics/Macro-Projects.html). In other words, A has a subproject macro with a package that exposes a macro (lets called it macrotools). Now both projects, A and B, use the macrotools package (and A and B are strictly separate projects, B uses A via dependancies in SBT, with A using publish-local)
Now, A using A's macrotools package is fine, everything works correctly. However when B uses A macrotools package, the following error happens
java.lang.IllegalAccessError: tried to access method com.monetise.waitress.types.Married$.<init>()V from class com.monetise.waitress.types.RelationshipStatus$
For those wondering, the macro is this one https://stackoverflow.com/a/13672520/1519631, so in other words, this macro is what is inside the macrotools package
This is also related to my earlier question Macro dependancy appearing in POM/JAR, except that I am now using SBT 0.13, and I am following the altered guide for SBT 0.13
The code being referred to above is, in this case, this is what is in B, and A is com.monetise.incredients.macros.tools (which is a dependency specified in build.sbt)
package com.monetise.waitress.types
import com.monetise.ingredients.macros.tools.SealedContents
sealed abstract class RelationshipStatus(val id:Long, val formattedName:String)
case object Married extends RelationshipStatus(0,"Married")
case object Single extends RelationshipStatus(1,"Single")
object RelationshipStatus {
// val all:Set[RelationshipStatus] = Set(
// Married,Single
// )
val all:Set[RelationshipStatus] = SealedContents.values[RelationshipStatus]
}
As you can see, when I use whats commented, the code works fine (the job of the macro is to fill the Set with all the case objects in an ADT). When I use the macro version, i.e. SealedContents.values[RelationshipStatus] is when I hit the java.lang.IllegalAccessError
EDIT
Here are the repos containing the projects
https://github.com/mdedetrich/projectacontainingmacro
https://github.com/mdedetrich/projectb
Note that I had to do some changes, which I forgot about earlier. Because the other project needs to depend on the macro as well, the following 2 lines to disable macro publishing have been commented out
publish := {},
publishLocal := {}
In the build.scala. Also note this is a runtime, not a compile time error
EDIT 2
Created a github issue here https://github.com/sbt/sbt/issues/874
This issue is unrelated to SBT. It looks like the macro from Iteration over a sealed trait in Scala? that you're using has a bug. Follow the link to see a fix.
In my quest to generate new code in a Scala compiler plugin, I have now created working classes. The next logical step is to put those classes in a new, non-existing package. In Java, a package is basically a directory name, but in Scala a package seems much more complicated. So far I haven't found/recognized an example where a compiler plugin creates a new package.
At my current level of understanding, I would think that I would need to create first a package symbol with:
parentPackage.newPackage(...)
// ...
and than later create a Tree for the package with PackageDef. But PackageDef doesn't take the symbol as parameter, as one would expect, and searching for:
Scala newPackage PackageDef
returned nothing useful. So it seems that I don't need to do those two steps together. Possibly one is done for my by the compiler, but I don't know which one. So far, what I have looks like this:
val newPkg = parentPackage.newPackage(NoPosition, newTermName(name))
newPkg.moduleClass.setInfo(new PackageClassInfoType(new Scope,
newPkg.moduleClass))
newPkg.setInfo(newPkg.moduleClass.tpe)
parentPackage.info.decls.enter(newPkg)
// ...
val newPkgTree = PackageDef(Ident(newPkg.name), List(ClassDef(...)))
I think my answer to your other question should answer this one as well:
How to add a new Class in a Scala Compiler Plugin?
here is my test case , while i right click the file eclipse doest not show any run as junit test option. I try to manual create run configuration but does not take any sense.
scala version:2.8.1 scalatest:1.3 eclipse:3.6.2
package org.jilen.cache.segment
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import org.scalatest.FlatSpec
import org.scalatest.matchers.ShouldMatchers
#RunWith(classOf[JUnitRunner])
class RandomSegmentSpec extends FlatSpec with ShouldMatchers {
val option = SegmentOptions()
"A Simple Segment" should "contains (douglas,lea) after put into" in {
val segment = RandomSegment.newSegment(option)
segment.put("douglas", "lea")
segment("douglas") should be("lea")
}
it should "return null after (douglas,lea) is remove" in {
val segment = RandomSegment.newSegment(option)
segment.put("douglas", "lea")
segment -= ("douglas")
segment("douglas") should equal(null)
}
it should "contains nothing after clear" in {
val segment = RandomSegment.newSegment(option)
segment.put("jilen", "zhang")
segment.put(10, "ten")
segment += ("douglas" -> "lea")
segment += ("20" -> 20)
segment.clear()
segment.isEmpty should be(true)
}
}
I've encountered this seemingly randomly, and I think I've finally figured out why.
Unfortunately the plugin doesn't yet change package declarations when you move files, nor the class names when you rename files. (Given you can put multiple classes in one file, the latter will likely never be done.) If you are used to the renamings being done automagically in Eclipse, like I am, you're bound to get caught on this.
So... check carefully the following:
the package declaration in your Scala file matches the Eclipse package name
the name of the test class in the Scala file matches the name of the Scala file
I just ran into this, fixed both, and now my test runs!
This is a known problem with the Eclipse IDE for Scala. I'm currently working on the plugin for this. Watch this space.
I found Scalatest to be very bad at integrating with Eclipse (running the tests from eclipse showed that it ran them - but they would not pass or fail, but simply show up as passive blank boxes).
For some reason I could NOT get it to work after 3 hours of trying things!
Finally I tried specs2 - and it worked (Scala 2.9, Junit4 and Eclipse 3.6)!
They have a great doc here:
http://etorreborre.github.com/specs2/guide/org.specs2.guide.Runners.html#Runners+guide
Since I don't care which testing framework to use, I will try Specs2 purely from the convenience point of view.