PowerMockito throwing ClassNotPreparedException even with #PrepareForTest using Scala Test - scala

I have the following test...
import org.scalatest.junit.JUnitRunner
...
#PowerMockRunnerDelegate(classOf[JUnitRunner])
#PrepareForTest(Array(classOf[AuditLog]))
class ConnectorAPITest extends path.FreeSpec with ShouldMatchers {
"Mocked Tests" - {
println("This got called in the mocked tests.")
PowerMockito.mockStatic(classOf[AuditLog]);
...
}
}
But when I run I get...
An exception or error caused a run to abort: The class com.paxata.services.log.AuditLog not prepared for test.
To prepare this class, add class to the '#PrepareForTest' annotation.
In case if you don't use this annotation, add the annotation on class or method level.
org.powermock.api.mockito.ClassNotPreparedException:
The class com.paxata.services.log.AuditLog not prepared for test.
To prepare this class, add class to the '#PrepareForTest' annotation.
Which doesn't make sense given the annotation is already there? Is it an idiosyncrasy of Scala test?

I had the same problem using FunSuite. It works when I turned to JUnit.
#RunWith(classOf[PowerMockRunner])
#PrepareForTest(Array(classOf[SomeStaticClass]))
class MyTestClass {
#Before
def setUp {
PowerMockito.mockStatic(classOf[SomeStaticClass])
Mockito.when(SomeStaticClass.getSomeObject(1)).thenReturn(new SomeObject(1))
}
#Test
def someTestMethod {
}
etc...

Related

Spark Unit Testing: How to initialize sc only once for all the Suites using FunSuite

I want to write spark unit test cases and I am using FunSuite for it.
But i want that my sparkContext is initialized only once , used by all the Suites and then is killed when all Suites completes.
abstract class baseClass extends FunSuite with BeforeAndAfter{
before {
println("initialize spark context")
}
after {
println("kill spark context")
}
}
#RunWith(classOf[JUnitRunner])
class A extends baseClass{
test("for class A"){
//assert
}
#RunWith(classOf[JUnitRunner])
class B extends baseClass{
test(for class b){
//assert
}
}
but when i run sbt test
I can see println statement baseClass has been called from both the tests. Obsiously When the object is created for both the classes A and B , Abstract
baseclass is called.
But then how can we achieve my purpose i.e spark context is iniliazed only once while all the test cases are run
Option 1: Use the excellent https://github.com/holdenk/spark-testing-base library that does exactly that (and provides many other nice treats). After following the readme, it's as simle as mixing-in SharedSparkContext instead of your baseClass, and you'll have an sc: SparkContext value ready to use in your test
Option 2: to do it yourself, you'd want to mix-in BeforeAndAfterAll and not BeforeAndAfter, and implement beforeAll and afterAll, which is exactly what the above-mentioned SharedSparkContext does.
I strongly recommend using the spark-testing-base library in order to manage the lifecycle of a sparkContext or sparkSession during your tests.
You won't have to pollute your tests by overriding the beforeAll, afterAll methods and managing the lifecycle of the sparkSession/sparkContext.
You can share one sparkSession/sparkContext for all the tests by overriding the following method :
def reuseContextIfPossible: Boolean = true
for more details : https://github.com/holdenk/spark-testing-base/wiki/SharedSparkContext
I hope it helps!
If you really want to share the context between suites - you'll have to make it static. Then you can use a lazy value to make it start on first use. As for shutting it down - you can leave it to the automatic Shutdown hook created each time a context is created.
It would look something like:
abstract class SparkSuiteBase extends FunSuite {
lazy val sparkContext = SparkSuiteBase.sparkContext
}
// putting the Spark Context inside an object allows reusing it between tests
object SparkSuiteBase {
private lazy val sparkContext = ??? // create the context here
}

Access inner class method with "fine" syntax in Java using Scala class & object

I have the following scala example:
class Nested {}
object Nested {
class Inner {}
object Inner {
def x = 321
}
}
With a JUnit test to test specifically that I can do Nested.Inner.x() and call the method freely without the Nested.Inner$.MODULE$.x():
import static junit.framework.Assert.*;
import org.junit.Test;
public class TestFromJava {
#Test
public void accessTest() {
assertEquals(321, Nested.Inner.x());
}
}
This compiles, but at the moment of running the test, I am getting (sbt test):
[error] TestFromJava.java:8: cannot find symbol
[error] symbol: method x()
[error] location: class Nested.Inner
[error] Nested.Inner.x
How can I benefit from both Scala syntax and not using the horrible $? Maybe it is a feature of the language as how it generates the object instances.
You have to qualify singleton object access when calling from Java, as explained in this question.
In your case that would be
Nested.Inner$.MODULE$.x()

How to make JUnit4 lifecycle callbacks work in ScalaTest with JUnitRunner?

According to ScalaTest documentation it's possible to use JUnitRunner to run tests. My assumption was, if it runs with JUnitRunner, its callback methods (i.e. methods marked with #Before or #After annotation should work as well. But apparently my assumption was wrong. I've created simple example to demonstrate it:
import org.junit.Before
import org.junit.runner.RunWith
import org.scalatest.{FunSuite, _}
import org.scalatest.junit.JUnitRunner
#RunWith(classOf[JUnitRunner])
class Test extends FunSuite {
#Before
def before() = {
println("before test")
}
test("nothing") {
println("test is started")
}
}
If you run this example, you'll see test is started line, but not before test.
I'm aware of ScalaTest lifecycle callbacks, but the thing is I need to make JUnit callbacks work somehow. I want to write a test for Play 2.4 application and the thing it's play.test.WithBrowser class relies on JUnit callbacks. I found this workaround for the issue:
var testBrowser : TestBrowser = _
before {
new WithBrowser {
override def createBrowser(): Unit = {
super.createBrowser()
testBrowser = browser
}
}.createBrowser()
}
but I believe it's quite ugly and I suspect that there is a better way.
So, my question is if it's possible to make these JUnit lifecycle callbacks work with ScalaTest? And if it is possible, how to do that?
You should be able to do this using JUnitSuite instead of FunSuite. The documentation is here:
http://www.scalatest.org/getting_started_with_junit_4_in_scala
http://doc.scalatest.org/2.2.4/index.html#org.scalatest.junit.JUnitSuite
I did just like Noah suggested and it worked. Just in case anyone stumbles upon the same issue with Play 2.x and WithBrowser, I ended up with a test like this:
class IntegrationSpec extends WithBrowser with JUnitSuiteLike with Matchers {
#Test def workWithBrowser() {
browser.goTo("http://localhost:9000")
browser.pageSource should include("Add Person")
}
}

How to enforce scala macro annotation constraints on annotated classes?

I am trying to implement a "simple" util library that puts annotated scalatest suite in a Suites instance to give them a certain running context.
trait MyContext extends BeforeAndAfterAll {
//declarations of values
override def beforeAll() = {/* run various init procedures */}
override def afterAll() = {/* tear everything down */}
}
That part works and I can use it if I code the Suites instance myself.
What I would like to code is scala annotations with a macro that will take all annotated org.scalatest.Suite subtypes and generate the Suites class as in:
class testThisInContext extends StaticAnnotation{ /* ... */}
#testThisInContext
class TestOne extends WordSpec {}
#testThisInContext
class TestTwo extends FlatSuite {}
And would then generated:
class InContextSuites extends Suites(new TestOne, new TestTwo) with MyContext {}
and also modify the classes by adding the #org.scalatest.DoNotDiscover annotation to them (to avoid execution out of context).
I need a way to interrupt the application of the macro (and throw an error) when the annotated class is not a subclass of Suite (which would make the generated class not compile).
I also have not figured out how to type check annotations in the modifiers instance of a ClassDef (in order to add an annotation if needed).

#Test method in Scala trait not found

does somebody know why #Test annotated methods which are inherited from a Scala trait are not found by the JUnit 4 test runner? It gives me "No JUnit tests found".
class FooTests extends BarTesting
But the following modification works?
import junit.framework.TestCase
class FooTests extends TestCase with BarTesting
In the Scala trait BarTesting I defined methods with the following signature.
#Test
final def testBar() {
// ...
}
This is indeed a bug in Eclipse. You can raise as such if you like. http://www.assembla.com/spaces/scala-ide/tickets.
When you extend TestCase the test is being run because it starts with test, not because of the annotation. There was a problem with recognition of annotations, which is how the junit stuff works, and I haven't looked to see if it is fixed yet to make the junit stuff work.
Your best bet is to:
Raise the bug against scala-ide
Add #RunWith[classOf[JUnit]) to your class
The following works:
trait BarTesting {
#Test final def testBar() {
println("Hello world")
}
}
#RunWith(classOf[JUnit4])
class FooTesting extends BarTesting {
}
And I'll try and fix the bug.
EDIT: In the latest versions of scala-ide (as of 9 November 2011), this now works.