How to Test a Play Application that extends a custom trait - scala

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.

Related

When I run my test suites they fail with PSQLException: FATAL: sorry, too many clients already

I'm writing tests for my Play application and I want to run them with a real server so that I can fake all the answers from the external services.
In order to do that I extend PlaySpec and GuiceOneServerPerSuite and I override the method fakeApplication to create my routes and give them to the Guice Application
class MySpec extends PlaySpec with GuiceOneServerPerSuite {
override def fakeApplication(): Application =
GuiceApplicationBuilder().appRoutes(app => {
case ("POST", "/url/") => app.injector.instanceOf(classOf[DefaultActionBuilder]) { Ok }
}).globalApp(true).build()
"Something" should {
"work well" in {
val wsClient = app.injector.instanceOf[WSClient]
val service = new MyService(wsClient)
service.method() mustBe ""
app.injector.instanceOf[DBApi].databases().foreach(_.getConnection().close())
}
}
}
I have multiple test suites like this one and if I run them alone they work fine, but if I run them all together they fill up the connection pool and then everything fails with: org.postgresql.util.PSQLException: FATAL: sorry, too many clients already.
My considerations: I think it happens because at each test suite a new Play Guice Application is created. I also tried to close the connections of all databases manually but didn't solve the problem.
We had the same problems, so we are separating these 2 use cases (running all or just one Test-Suite).
This makes running all tests much faster - as Play Environment is only started once.
The Suite looks like:
class AcceptanceSpecSuite
extends PlaySpec
with GuiceOneAppPerSuite
with BeforeAndAfter {
// all specs
override def nestedSuites: immutable.IndexedSeq[AcceptanceSpec] = Vector(
// api
new DatabaseTaskSpec,
new HistoryPurgeTaskSpec,
...
)
override def fakeApplication(): Application =
// your initialization
}
Now each Spec looks like:
#DoNotDiscover // important that it is run only if called explicitly
class DatabaseTaskSpec extends AcceptanceSpec {
...
The Parent class now we can switch between GuiceOneServerPerSuite and ConfiguredApp:
trait AcceptanceSpec
extends PlaySpec
you need:
// with GuiceOneServerPerSuite // if you want to test only one Test
with ConfiguredApp // if you want to test all
with Logging
with ScalaFutures
with BeforeAndAfter {
...
I know it's a bit of a hack - so I am also interested in a more elegant solution;).
You can put your DB instance as a singleton, if you do that, he won´t create multiple instance, therefore won´t fill the connection pool.
Something like that:
#Singleton
object TestDBProperties extends DBProperties {
override val db: Database = Database.forURL(
url = "jdbc:h2:mem:testdb;MODE=MYSQL;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=FALSE;",
driver = "org.h2.Driver")
}
Hope this helps.

Testing object which calls another object in Scala using Specs2

I'm working with a project which already has some legacy code written in Scala. I was given a task to write some unit tests for one of its classes when I discovered it's not so easy. Here's the problem I've encountered:
We have an object, say, Worker and another object to access the database, say, DatabaseService which also extends other class (I don't think it matters, but still). Worker, in its turn, is called by higher classes and objects.
So, right now we have something like this:
object Worker {
def performComplexAlgorithm(id: String) = {
val entity = DatabaseService.getById(id)
//Rest of the algorithm
}
}
My first though was 'Well, I can probably make a trait for DatabaseService with the getById method'. I don't really like the idea to create an interface/trait/whatever just for the sake of testing because I believe it doesn't necessarily lead to a nice design, but let's forget about it for now.
Now, if Worker was a class, I could easily use DI. Say, via constructor like this:
trait DatabaseAbstractService {
def getById(id: String): SomeEntity
}
object DatabaseService extends SomeOtherClass with DatabaseAbstractService {
override def getById(id: String): SomeEntity = {/*complex db query*/}
}
//Probably just create the fake using the mock framework right in unit test
object FakeDbService extends DatabaseAbstractService {
override def getById(id: String): SomeEntity = {/*just return something*/}
}
class Worker(val service: DatabaseService) {
def performComplexAlgorithm(id: String) = {
val entity = service.getById(id)
//Rest of the algorithm
}
}
The problem is, Worker is not a class so I can't make an instance of it with another service. I could do something like
object Worker {
var service: DatabaseAbstractService = /*default*/
def setService(s: DatabaseAbstractService) = service = s
}
However, it scarcely makes any sense to me since it looks awful and leads to an object with mutable state which doesn't seem very nice.
The question is, how can I make the existing code easily testable without breaking anything and without making any terrible workarounds? Is it possible or should I change the existing code instead so that I could test it easier?
I was thinking about using extending like this:
class AbstractWorker(val service: DatabaseAbstractService)
object Worker extends AbstractWorker(DatabaseService)
and then I somehow could create a mock of Worker but with different service. However, I didn't figure out how to do it.
I'd appreciate any advice as to how either change the current code to make it more testable or test the existing.
If you can alter the code for Worker, you can change it to still allow it to be an object and also allow for swapping of the db service via an implicit with a default definition. This is one solution and I don't even know if this is possible for you, but here it is:
case class MyObj(id:Long)
trait DatabaseService{
def getById(id:Long):Option[MyObj] = {
//some impl here...
}
}
object DatabaseService extends DatabaseService
object Worker{
def doSomething(id:Long)(implicit dbService:DatabaseService = DatabaseService):Option[MyObj] = {
dbService.getById(id)
}
}
So we set up a trait with concrete impl of the getById method. Then we add an object impl of that trait as a singleton instance to use in the code. This is a good pattern to allow for mocking of what was previously only defined as an object. Then, we make Worker accept an implicit DatabaseService (the trait) on it's method and give it a default value of the object DatabaseService so that regular use does not have to worry about satisfying that requirement. Then we can test it like so:
class WorkerUnitSpec extends Specification with Mockito{
trait scoping extends Scope{
implicit val mockDb = mock[DatabaseService]
}
"Calling doSomething on Worker" should{
"pass the call along to the implicit dbService and return rhe result" in new scoping{
mockDb.getById(123L) returns Some(MyObj(123))
Worker.doSomething(123) must beSome(MyObj(123))
}
}
Here, in my scope, I make an implicit mocked DatabaseService available that will supplant the default DatabaseService on the doSomething method for my testing purposes. Once you do that, you can start mocking out and testing.
Update
If you don't want to take the implicit approach, you could redefine Worker like so:
abstract class Worker(dbService:DatabaseService){
def doSomething(id:Long):Option[MyObj] = {
dbService.getById(id)
}
}
object Worker extends Worker(DatabaseService)
And then test it like so:
class WorkerUnitSpec extends Specification with Mockito{
trait scoping extends Scope{
val mockDb = mock[DatabaseService]
val testWorker = new Worker(mockDb){}
}
"Calling doSomething on Worker" should{
"pass the call along to the implicit dbService and return rhe result" in new scoping{
mockDb.getById(123L) returns Some(MyObj(123))
testWorker.doSomething(123) must beSome(MyObj(123))
}
}
}
In this way, you define all the logic of importance in the abstract Worker class and that's what you till focus your testing on. You provide a singleton Worker via an object that is used in the code for convenience. Having an abstract class let's you use a constructor param to specify the database service impl to use. This is semantically the same as the previous solution but it's cleaner in that you don't need the implicit on every method.

Using Mockito in Scala with Spec2

This is in the context of Play framework. I have a controller that instantiates a Validator. Validator has validate method. Controller has a method putEnity() that validates the payload it receives using this validate().
For unit testing the controller, i would like to mock the call Validator.validate(). TestController looks like this
class EntityControllerTest extends FlatSpec with Mockito {
def testPutEntity() = {
val payload = createPayload()
val mockValidator = mock[Validator]
when(mockValidator.validate(anyString, anyString)).thenReturn(EntityValidationResult(true, "Test"))
EntityController.putEntity(payload)
}
The problem is that, this mock call is not being used but the actual validate() is called and hence the test fails.
How can i fix this
The problem is that in your final line:
EntityController.putEntity(payload)
you are effectively calling a static method on EntityController, and despite all your attempts to configure a mock Validator you've never had an opportunity to "inject it" into the controller.
It's going to be a little bit difficult to suggest an ideal solution without seeing how you've implemented your controller, but at a guess, you'd want to do something like the following to allow a mocked Validator to be injected for testing, but for everything else to work like before.
I'll step through it to (hopefully) make it clearer:
Step 1 - make EntityController instantiable:
You've probably got something like this:
object EntityController extends Controller {
...
def putEntity = Action ...
..
}
Replace it with this:
class EntityControl extends Controller {
...
def putEntity = Action ...
...
}
object EntityController extends EntityControl
Now you've given yourself the ability to new something with the same behaviour as your "production" object. But we need to be able to substitute in a mock validator...
Step 2 - require a validator instance in your EntityControl:
Your old EntityController object probably had something like this:
object EntityController extends Controller {
val validator = new Validator(...)
...
}
which is why you could never get your mocked validator involved. Let's inject it as a constructor parameter so it can't be forgotten:
class EntityControl(val validator:Validator) extends Controller {
...
}
object EntityController extends EntityControl(new Validator(...))
So again, our "production" EntityController object has all the functionality we used to have, but the key difference is that we've exposed a "testing seam" to allow a mock to be injected when needed.
Step 3 - inject, and test!
Flip to your test spec, and set up a testable EntityControl instance
class EntityControllerTest extends FlatSpec with Mockito {
def testPutEntity() = {
val payload = createPayload()
val mockValidator = mock[Validator]
when(mockValidator.validate(anyString, anyString)).thenReturn(EntityValidationResult(true, "Test"))
val myTestableEC = new EntityControl(mockValidator)
myTestableEC.putEntity(payload)
}
As you develop more test cases, you'll probably want to extract the setup-and-wiring parts of the test into a suitable function, or even a Specs2 Scope.
Hope this helps, and clarifies a few effective unit testing ideas for you too.

Exclude particular test subclass in ScalaTest (maven)

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.

How to do setup/teardown in specs2 when using "in new WithApplication"

I am using Specs2 with play 2.2.1 built with Scala 2.10.2 (running Java 1.7.0_51). I have been reading about how to do setup/teardown with Specs2. I have seen examples using the "After" trait as follows:
class Specs2Play extends org.specs2.mutable.Specification {
"this is the first example" in new SetupAndTeardownPasswordAccount {
println("testing")
}
}
trait SetupAndTeardownPasswordAccount extends org.specs2.mutable.After {
println("setup")
def after = println("teardown ")
}
This works fine, except that all of my tests are using "in new WithApplication". It seems what I need is to have an object which is both a "WithApplication" and an "After". Below does not compile, but is essentially what I want:
trait SetupAndTeardownPasswordAccount extends org.specs2.mutable.After with WithApplication
So, my question is, how do I add setup/teardown to my tests which are already using "in WithApplication"? My primary concern is that all of our tests make use of fake routing like this (so they need the With Application).
val aFakeRequest = FakeRequest(method, url).withHeaders(headers).withBody(jsonBody)
val Some(result) = play.api.test.Helpers.route(aFakeRequest)
result
This is the code for WithApplication:
abstract class WithApplication(val app: FakeApplication = FakeApplication()) extends Around with Scope {
implicit def implicitApp = app
override def around[T: AsResult](t: => T): Result = {
Helpers.running(app)(AsResult.effectively(t))
}
}
It's actually quite easy to modify this to suit your needs without creating a bunch of other traits. The missing piece here is the anonymous function t, which you provide the implementation for in your tests (using WithApplication). It would be nice to make WithApplication a little more robust to be able to execute arbitrary blocks of code before and after the tests, if necessary.
One approach could be to create a similar class to WithApplication that accepts two anonymous functions setup and teardown that both return Unit. All I really need to do is modify what's happening inside AsResult.effectively(t). To keep this simple, I'm going to remove the app parameter from the parameter list, and use FakeApplication always. You don't seem to be providing a different configuration, and it can always be added back.
abstract class WithEnv(setup: => Unit, teardown: => Unit) extends Around with Scope {
implicit def implicitApp = app
override def around[T: AsResult](t: => T): Result = {
Helpers.running(app)(AsResult.effectively{
setup
try {
t
} finally {
teardown
}
})
}
}
Instead of simply calling the anonymous function t, I first call setup, then t, then teardown. The try/finally block is important because failed tests in specs2 throw exceptions, and we want to be sure that teardown will be executed no matter what the outcome.
Now you can easily setup test environments using functions.
import java.nio.files.{Files, Paths}
def createFolder: Unit = Files.createDirectories(Paths.get("temp/test"))
def deleteFolder: Unit = Files.delete("temp/test")
"check if a file exists" in new WithEnv(createFolder, deleteFolder) {
Files.exists(Paths.get("temp/test")) must beTrue
}
(This might not compile, but you get the idea.)
If your after method doesn't need anything from the WithApplication trait you can mix in your specification the AfterExample trait and define the after behaviour for the whole spec:
import org.specs2.specification._
class Specs2Play extends org.specs2.mutable.Specification with AfterExample {
"this is the first example" in new SetupAndTeardownPasswordAccount {
pending("testing")
}
trait SetupAndTeardownPasswordAccount extends WithApplication
def after = println("cleanup")
}