Exclude particular test subclass in ScalaTest (maven) - scala

I have one superclass with WordSpecLike and several subclasses for each backend.
abstract class A extends TestKit(_system) with WordSpecLike {
"backend" must {
"do something useful" in {
//test useful stuff
}
"print something pretty" in {
//test pretty print
}
}
}
class B extends A {
}
class C extends A {
}
C and B tests different backends but the thing is I need to turn on/off each backend-test separately for integration tests (using exclude groups).
Obviously, I can't use taggedAs.
Using a separate traits like in a bellow example didn't work:
trait backendB { this: Tag =>
override val name = "backendB"
}
class B extends A with backendB {
//...
}
}
Pure java annotation didn't work ether:
#TagAnnotation
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD, ElementType.TYPE})
public #interface backendB {
}
So, the question is: Have I any other options to run each backend test under a special group or I have to copy-paste code?
Scala version 2.10
ScalaTest version 2.2.2
Java version 1.8.0_20
Can't use sbt instead of maven, can't bump scala version.

If I understand correctly, you want sometimes to exclude class B and run just class C. Other times exclude class C and run just class B. If that's correct, then normally you would annotate B and C with a respective tag annotation (make using Java). For example, doing this would cause all tests of B to be tagged as backendB:
#backendB
class B extends A {
}
What you didn't show is where the actor system is coming from. One thing about tags is that it only excludes tests, an instance of B will still be created. That means any state it holds onto will be initialized, and that might in your case mean an actor system. This might be what you meant by "didn't work." If so, my usual advice is to make that state lazily initialized. The instance will still be created, but because no tests run, he state will never be accessed, and since it is lazy, will never be initialized.
Since there are a lot of unknowns in this reply, you might do better on scalatest-users, where it is easier to go back and forth.

Ok, my final solution is not so elegant as it could be but it's work at least (still kinda more java-way solution).
Several small changes:
trait A-suite extends WordSpecLike {
val tagToExclude = Tag("here we can write anything")
def createTestBackend: Backend
"backend" must {
"do something useful" taggedAs(tagToExclude) in {
val backend = createTestBackend
//test useful stuff
}
"print something pretty" taggedAs(tagToExclude) in {
val backend = createTestBackend
//test pretty print
}
}
}
And test classes for different backends:
`
class backendA(override val tagToExclude = "backendA") extends A-suite {
override def createTestBackend: Backend = new backendA
}
class backendB(override val tagToExclude = "backendB") extends A-suite {
override def createTestBackend: Backend = new backendB
}
Now exclude groups work properly with maven.

Related

Is it possible to have the view implementation hidden in a Scala application?

My goal is to have an MVC pattern in a simulation application where the controller knows there is a view (and interacts with it using an interface) but doesn't know how it is implemented:
object Controller extends App {
View.initView()
...
}
object View {
stage: Stage = ...
def initView: Unit = {
...
}
}
However I only managed to do so having the entry point of the program to extend scalafx.application.JFXApp, javafx.application.Application (example below) or swing.SimpleSwingApplication which forces the controller to know how the view is implemented. Is there any simple workaround?
def main(args: Array[String]): Unit = {
Application.launch(classOf[SimulatorApp])
}
class SimulatorApp extends Application {
override def start(stage: Stage): Unit = {
View.initView(stage)
}
}
Well, you can design your application as abstract e.g.
class MyApplication(dependency1: Dependency1, dependency2: Dependency2)
extends Application {
// code using things
}
and then pass implementations somewhere else
class MyApplicationImplemented
extends MyApplication(implementation1, implentation2)
Application.launch(classOf[MyApplicationImplemented])
where dependencies could be:
instances
recipes for instances (functions)
configs
etc.
You can also make some methods abstract and implement them in some top level.
In general you treat your final Application implementation as class with main method - this is not an object you pass dependencies into but a place where you finally wire them together. So in the end you have to design it to be your main. (launch methods' signatures confirm that this is the intent).
That said a lot of logic can be extracted into traits or abstract classes or components so that you could have some general logic somewhere else, have it rely on dependency injection, create several implementations, and wire them in separate "mains" for e.g. production code and end-to-end tests.

Is it possible to mock / override dependencies / imports in Scala?

I have some code looking like this:
package org.samidarko.actors
import org.samidarko.helpers.Lib
class Monitoring extends Actor {
override def receive: Receive = {
case Tick =>
Lib.sendNotification()
}
}
Is there a way to mock/stub Lib from ScalaTest like with proxyquire for nodejs?
I read that I could use dependency injection but I would rather not do that
Is my only alternative is to pass my lib as class parameter?
class Monitoring(lib: Lib) extends Actor {
Any advice to make it more testable? Thanks
EDIT:
Xavier Guihot's answer is an interesting approach of the problem but I choose to change the code for testing purpose.
I'm passing the Lib as parameter and I'm mocking with mockito, it makes the code easier to test and to maintain than shadowing the scope.
This answer only uses scalatest and doesn't impact the source code:
Basic solution:
Let's say you have this src class (the one you want to test and for which you want to mock the dependency):
package com.my.code
import com.lib.LibHelper
class MyClass() {
def myFunction(): String = LibHelper.help()
}
and this library dependency (which you want to mock / override when testing MyClass):
package com.lib
object LibHelper {
def help(): String = "hello world"
}
The idea is to create a class in your test folder which will override/shadow the library. The class will have the same name and the same package as the one you want to mock. In src/test/scala/com/external/lib, you can create LibHelper.scala which contains this code:
package com.lib
object LibHelper {
def help(): String = "hello world - overriden"
}
And this way you can test your code the usual way:
package com.my.code
import org.scalatest.FunSuite
class MyClassTest extends FunSuite {
test("my_test") {
assert(new MyClass().myFunction() === "hello world - overriden")
}
}
Improved solution which allows setting the behavior of the mock for each test:
Previous code is clear and simple but the mocked behavior of LibHelper is the same for all tests. And one might want to have a method of LibHelper produce different outputs. We can thus consider setting a mutable variable in the LibHelper and updating the variable before each test in order to set the desired behavior of LibHelper. (This only works if LibHelper is an object)
The shadowing LibHelper (the one in src/test/scala/com/external/lib) should be replaced with:
package com.lib
object LibHelper {
var testName = "test_1"
def help(): String =
testName match {
case "test_1" => "hello world - overriden - test 1"
case "test_2" => "hello world - overriden - test 2"
}
}
And the scalatest class should become:
package com.my.code
import com.lib.LibHelper
import org.scalatest.FunSuite
class MyClassTest extends FunSuite {
test("test_1") {
LibHelper.testName = "test_1"
assert(new MyClass().myFunction() === "hello world - overriden - test 1")
}
test("test_2") {
LibHelper.testName = "test_2"
assert(new MyClass().myFunction() === "hello world - overriden - test 2")
}
}
Very important precision, since we're using a global variable, it is compulsory to force scalatest to run test in sequence (not in parallel). The associated scalatest option (to be included in build.sbt) is:
parallelExecution in Test := false
Not a complete answer (as I don't know AOP very well), but to put you in the right direction, this is possible through Java lib called AspectJ:
https://blog.jayway.com/2007/02/16/static-mock-using-aspectj/
https://www.cakesolutions.net/teamblogs/2013/08/07/aspectj-with-akka-scala
Example in pseudocode (without going into details):
class Mock extends MockAspect {
#Pointcut("execution (* org.samidarko.helpers.Lib.sendNotification(..))")
def intercept() {...}
}
The low level basics of this approach are Dynamic Proxies: https://dzone.com/articles/java-dynamic-proxy. However, you can mock static methods too (maybe you'll have to add word static into the pattern).

Guice Assisted Inject with Providers or FactoryModuleBuilder

This is kind of a weird use-case and I need some help in figuring out how to use Assisted/Providers/FactoryModuleBuilders in conjunction with each other. Ignore the absence of #Singleton. This is just an example.
A set of traits belonging to a library I cannot change have the following pattern. It uses Cake Pattern.
trait A { //Has abstract methods and abstract service 'webService' }
trait B extends A { //First Concrete Service Implementation assigned to 'webService' }
trait C extends A { //Second Concrete service Implementation assigned to 'webService' }
Since the traits cannot be directly injected, I created a wrapper that would allow them to be injected
BB extends B
CC extends C
In my code, I have a Controller that depends on a Service, that in turn depends on the library. The service should be able to either use "BB" or "CC" depending on what the controller needs. So the components look like the following
I create my service as
//Note: Uses 'trait A' with #Assisted
class SomeWebServiceComponent #Inject()(#Assisted aInstance: A, foo: Foo){
//Do something with aInstance
}
The Factory to create this (should be created by Guice by using FactoryModuleBuilder)
class SomeServiceFactory {
def getWebServiceComponent(a:A) SomeWebServiceComponent
}
The FactoryModule will look something like this
class ApplicationModule extends AbstractModule {
override def configure() = {
install(new FactoryModuleBuilder().build(classOf[SomeServiceFactory]))
}
}
I don't mind annotating the controllers with the actual classes that I need.
class OneController #Inject()(factory: SomeServiceFactory, bb: BB) extends Controller {
val webServiceComponent = factory.getWebServiceComponent(bb)
}
class AnotherController #Inject()(factory: SomeServiceFactory, cc: CC) extends Controller {
val webServiceComponent = factory.getWebServiceComponent(cc)
}
With this setup, I get errors of the following kind
No implementation for 'A' annotated with #com.google.inject.assistedinject.Assisted(value=) was bound
I need to understand how I can tell Guice that there are two implementations for Trait A, namely, BB and CC and the choice will be supplied at runtime.
Is there a way to achieve this use-case?
Ok, I created a separate project to test this whole scenario.
And it works the way the question is framed.
It turns out, the test cases that I were using, were not currently using GuiceInjection directly. The error message was however, so specifically related to GuiceInjection that I never investigated if the test setup was correct.
Changing the test base, resolved the issue.

How to Test a Play Application that extends a custom trait

I'm having trouble writing tests for a mixin to my Play application that runs in it's own thread separate from play. I've tried over-writing WithApplication.provideApplication method with no luck. I get an inheriting conflicting methods error. (one from the real app "MyRunnableSystemWrapper", one from my mocked fake mixin called "MyMockedSystemWrapper").
execute(system) runs my system that is tested elsewhere and has sideaffects (connects to networked services, thus failing this test when such things are not available. Good news is I have a mocked service of my system wrapper that uses a system which does NOT have side affects and DB/Network calls are mocked out. However I do not know how to give THIS MOCKED version of my app to "WithApplication" test.
Reduced Code for clarity:
class Application extends Controller with MyRunnableSystemWrapper {
val pool: ExecutorService = Executors.newFixedThreadPool(1)
val system = new MyRunnableSystem() //system is abstract in MRSW ^^^ above
pool.execute(system)
def index = Action {
OK("HI")
}
}
My Test:
class MyAppTest(implicit ee: ExecutionEnv) extends Specification {
abstract class WithMyMockApp extends WithApplication {
def provideApplication = new controllers.Application with MyMockedSystemWrapper // This imports MyRunnableSystemWrapper
}
"Sending a GET request" should {
"Respond with OK" in new WithMyMockApp {
val response = route(app, FakeRequest(GET, "/")).get
status(response) mustEqual OK
}
}
}
If I'm not running my Runnable in the correct place and should be calling it somewhere else to make this testing easier, let me know!
You could inject your system wrapper instead of extending it
trait SystemWrapper {
def execute(system: RunnableSystem)
}
class MyRunnableSystemWrapper extends SystemWrapper {...}
class MyMockedSystemWrapper extends SystemWrapper {...}
class Application #Inject() (systemWrapper SystemWrapper) extends Controller {
Then you need to tell Guice which implementation of SystemWrapper you want for runtime and which one for test. One way of doing this is by using different Guice modules for runtime/test which you set in your .conf files.

Little confused on the usefulness of beforeAll construct in ScalaTest

I have more of a philosophical confusion in-regards to the usefulness of methods like 'beforeAll' in scalaTest.
I have been looking for an answer why the need to even have constructs like beforeAll? I do understand that there is a reason why this design decision was taken but not able to think it through. Can anyone help?
e.g.
Suggested way as per tutorials online,
class TestExample extends FunSuite with BeforeAndAfterAll {
private var _tempDir: File = _
protected def tempDir: File = _tempDir
override def beforeAll(): Unit = {
super.beforeAll()
_tempDir = Utils.createTempDir(namePrefix = this.getClass.getName)
}
test("...") {
// using the variable in the function
}
}
vs
class TestExample extends FunSuite with BeforeAndAfterAll {
private val tempDir: File = Utils.createTempDir(namePrefix =
this.getClass.getName)
}
test("...") {
// Use the initialized variable here.
}
If you have cleanup to do in afterAll, I think it is symmetric to do setup in beforeAll. Also if you need to do some side effect that doesn't involve initializing instance variables, that can go in beforeAll. In the example you gave, though, where you don't have any cleanup to do in afterAll and all you're doing before all tests is initializing instance variables, I'd do with plain old initialization.
One other difference between val initializers and beforeAll is val initializers happen when the class is instantiated, whereas beforeAll happens later, when the instance is executed. If you want to delay the initialization until the class is run, you can use lazy vals.
One point worth noting is that some runners (such as the ScalaTest ant task, and Intellij IDEA), will instantiate all tests instances before running any tests. If your setup code happens to interact with any global variables or external state, then you probably want to defer those interactions until the test is run.
As a simple (contrived) example, suppose your code under test includes
Object Singleton {
var foo = ""
}
and you have two test classes:
class Test1 extends FunSuite {
Singleton.foo = "test1"
test("...") {
Singleton.foo should be("test1")
}
}
class Test1 extends FunSuite {
Singleton.foo = "test2"
test("...") {
Singleton.foo should be("test2")
}
}
If both classes are instantiated before any tests are run, then at least one of your two tests will fail. Conversely, if you defer your initialize work until beforeAll, you'll not see the same interference between tests.