Can I modify subcut modules in spray route test? - scala

I have a Specs2RouteTest
"test a route with some modified dependencies" in {
bindingModule.modifyBindings { implicit module =>
module.bind[AuthorizationService].toModuleSingle { createMockAuthService("1") }
val req = createMockRequest("1")
val testApi = module.inject [ApiEndpoints](None)
Post(s"/api/v1/service", JsonEntity(req.toJson)) ~> testApi.routes ~> check {
....
}
}
}
I confirm that the modified binding is set within the test. But once it gets into the route I am back to seeing the bindings as set up in the test module. Generally this modifyBindings{} technique seems to work to keep tests isolated and when I'm doing unit testing I can swap out dependencies no problem... but on these integration tests I can't seem to make the route under test pick up any binding modifications. Am I doing something obviously wrong?

Related

How to create mock object of main class to have partial integration test using PlaySpec?

There is a main class named 'MainProcess.scala' that I'm running some test cases for it. I wanno write an end to end test for this class to validate it's functionality.
Th problem here is the end to end test requires some criteria has to be established to be able to test whole functionality. For instance:
class MainProcess() {
def foo(someparams):Future[Boolean] = {
if criteria true else false
}
def bee(some params):Future[WSResponse] = {
// call a micro service
}
}
My question is: Is it a good practice to mock 'foo' method such that it always return true or mock 'bee' method so that test can pass through these modules and continue till it reaches the point I intend to see it's result. As I am testing this class, I know that mocking the same class results into error or malfunctionality of test case:
private def guiceApplicationBuilder(app: Application): Application = {
new GuiceApplicationBuilder()
.overrides(bind[MainProcess].toInstance(mainProcessMock))
.build()
}
If this is not a good practice, so how to do such stuff to mock specific modules of main class?
Thank you in advance.

Embedding multiple tests inside an akka-http route check

I'm using akka-http for the first time - my usual web framework of choice is http4s - and I'm having trouble getting the way I usually write endpoint unit tests to work with the route testing provided by akka-http-testkit.
Generally, I use ScalaTest (FreeSpec flavour) in order to set up an endpoint call and then run several separate tests on the response. For akka-http-testkit, this would look like:
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.testkit.ScalatestRouteTest
import org.scalatest.{FreeSpec, Matchers}
final class Test extends FreeSpec with ScalatestRouteTest with Matchers {
val route: Route = path("hello") {
get {
complete("world")
}
}
"A GET request to the hello endpoint" - {
Get("/hello") ~> route ~> check {
"should return status 200" in {
status should be(StatusCodes.OK)
}
"should return a response body of 'world'" in {
responseAs[String] should be("world")
}
//more tests go here
}
}
}
This errors with
java.lang.RuntimeException: This value is only available inside of a `check` construct!
The problem is the nested tests inside the check block - for some reason, values like status and responseAs are only available top-level within that block. I can avoid the error by saving the values I'm interested in to local variables top-level, but that's awkward and capable of crashing the test framework if e.g. the response parsing fails.
Is there a way around this, without putting all my assertions into a single test or performing a new request for each one?
You can group your test like that
"A GET request to the hello endpoint should" in {
Get("/hello") ~> route ~> check {
status should be(StatusCodes.OK)
responseAs[String] should be("world")
//more tests go here
}
}

Session doesn't work after upgrade to Play Framework 2.5.4, Scala

After upgrading my project to Play Framework 2.5.4 from 2.4.8, I'm having issue while working with session. There are to methods in my controller to test the issue:
def test = Action { implicit request =>
Redirect(controllers.routes.Carts.test2()).withSession(new Session(Map("user" -> "customer")))
}
def test2 = Action { implicit request =>
Ok(request.session.data.toString())
}
Basically test method adds session and redirects to test2 method. When I open page with test method url after redirect I'm getting what I need in the browser:
Map(user -> customer)
But if I refresh page after that I'm getting:
Map(csrfToken ->
ce1a6222484f378d38ab3534c2b400191270395d-1470238791014-c988ce3fe47259173166949a)
So, seems like session works for one request only and then overwrites with csrfToken. I have disabled all the filters. My class with filters looks like this:
class Filters #Inject() () extends HttpFilters {
val filters = Seq.empty
}
Can't understand what is wrong with my code. The same code was working fine before upgrade.
Check in ur application.conf if session.secure is true bring it to
play.http.session.secure=false

Specs2/Guice issue in Play 2.4.0 functional tests

I'm having an issue with dependencies apparently bleeding between tests, which is causing most of the tests to fail. In each case, debugging shows the first app created in a test class is used for all tests, and this is resulting in the failures.
I've tried adding isolated and sequential and this has had no effect.
Am I doing something remarkably stupid or subtly stupid?
For example, here's SubjectNotPresentTest.scala
class SubjectNotPresentTest extends AbstractViewTest {
"show constrained content when subject is not present" in new WithApplication(testApp(handler())) {
val html = subjectNotPresentContent(FakeRequest())
private val content: String = Helpers.contentAsString(html)
content must contain("This is before the constraint.")
content must contain("This is protected by the constraint.")
content must contain("This is after the constraint.")
}
"hide constrained content when subject is present" in new WithApplication(testApp(handler(subject = Some(user())))) {
val user = new User("foo", Scala.asJava(List.empty), Scala.asJava(List.empty))
val html = subjectNotPresentContent(FakeRequest())
private val content: String = Helpers.contentAsString(html)
content must contain("This is before the constraint.")
content must not contain("This is protected by the constraint.")
content must contain("This is after the constraint.")
}
}
GuiceApplicationBuilder is used in a parent class is used to create the app for testing.
val app = new GuiceApplicationBuilder()
.bindings(new DeadboltModule())
.bindings(bind[HandlerCache].toInstance(LightweightHandlerCache(handler)))
.overrides(bind[CacheApi].to[FakeCache])
.in(Mode.Test)
.build()
You can see an example of the failures at https://travis-ci.org/schaloner/deadbolt-2-scala/builds/66369307#L805
All tests can be found at https://github.com/schaloner/deadbolt-2-scala/tree/master/code/test/be/objectify/deadbolt/scala/views
Thanks,
Steve
It looks like the problem is caused when the current Play application is statically referenced in a test environment in which there are multiple applications - even if they are logically separate.
Because components can't be injected (to the best of my knowledge) into templates, I created a helper object which uses Play.current.injector to define a couple of vals.
val viewSupport: ViewSupport = Play.current.injector.instanceOf[ViewSupport]
val handlers: HandlerCache = Play.current.injector.instanceOf[HandlerCache]
(It's also not possible, TTBOMK, to inject into objects, otherwise I could just inject the components into the object and everyone could go home).
A better approach is to expose what is required as an implicit.
object ViewAccessPoint {
private[deadbolt] val viewStuff = Application.instanceCache[ViewSupport]
private[deadbolt] val handlerStuff = Application.instanceCache[HandlerCache]
object Implicits {
implicit def viewSupport(implicit application: Application): ViewSupport = viewStuff(application)
implicit def handlerCache(implicit application: Application): HandlerCache = handlerStuff(application)
}
}
In the view, import the implicits and you're good to go.
#import be.objectify.deadbolt.scala.DeadboltHandler
#import be.objectify.deadbolt.scala.ViewAccessPoint.Implicits._
#import play.api.Play.current
#(handler: DeadboltHandler = handlerCache(current).apply(), name: String, meta: String = null, timeout: Function0[Long] = viewSupport.defaultTimeout)(body: => play.twirl.api.Html)(implicit request: Request[Any])
#if(viewSupport.dynamic(name, meta, handler, timeout(), request)) {
#body
}

is there a scalaTest mechanism similar to TestNg dependsOnMethods annotation

Can I have dependencies between scalaTest specs such that if a test fails, all tests dependent on it are skipped?
I didn't add that feature of TestNG because I didn't at the time have any compelling use cases to justify it. I have since collected some use cases, and am adding a feature to the next version of ScalaTest to address it. But it won't be dependent tests, just a way to "cancel" a test based on an unmet precondition.
In the meantime what you can do is simply use Scala if statements to only register tests if the condition is met, or to register them as ignored if you prefer to see it output. If you are using Spec, it would look something like:
if (databaseIsAvailable) {
it("should do something that requires the database") {
// ...
}
it ("should do something else that requires the database") {
}
}
This will only work if the condition will be met for sure at test construction time. If the database for example is supposed to be started up by a beforeAll method, perhaps, then you'd need to do the check inside each test. And in that case you could say it is pending. Something like:
it("should do something that requires the database") {
if (!databaseIsAvailable) pending
// ...
}
it("should do something else that requires the database") {
if (!databaseIsAvailable) pending
// ...
}
Here is a Scala trait that makes all test in the test suite fail, if any test fails.
(Thanks for the suggestion, Jens Schauder (who posted another answer to this question).)
Pros: Simple-to-understand test dependencies.
Cons: Not very customizable.
I use it for my automatic browser tests. If something fails, then usually there's no point in continuing interacting with the GUI since it's in a "messed up" state.
License: Public domain (Creative Common's CC0), or (at your option) the MIT license.
import org.scalatest.{Suite, SuiteMixin}
import scala.util.control.NonFatal
/**
* If one test fails, then this traits cancels all remaining tests.
*/
trait CancelAllOnFirstFailure extends SuiteMixin {
self: Suite =>
private var anyFailure = false
abstract override def withFixture(test: NoArgTest) {
if (anyFailure) {
cancel
}
else try {
super.withFixture(test)
}
catch {
case ex: TestPendingException =>
throw ex
case NonFatal(t: Throwable) =>
anyFailure = true
throw t
}
}
}
I don't know about a ready made solution. But you can fairly easily write your own Fixtures.
See "Composing stackable fixture traits" in the javadoc of the Suite trait
Such a fixture could for example replace all test executions after the first one with calls to pending
You can use trait org.scalatest.CancelAfterFailure to cancel remaining tests after first failure:
import org.scalatest._
class MySpec extends FunSuite with CancelAfterFailure {
test("successfull test") {
succeed
}
test("failed test") {
assert(1 == 0)
}
test("this test and all others will be cancelled") {
// ...
}
}