I am trying to get the following urls to respond
/book/[bookname] (working)
/book/getdetails/[bookname] (working)
/book/[bookname]/page/[pagenumber] (working)
/book/[bookname]/page/getdetails/[pagenumber] (not working)
/book/[bookname]/page/test (working)
Basic Service handler:
class Service(object):
def __init__(self):
self.book = Book()
#cherrypy.expose
def index(self):
return 'normal page'
Books Class:
#cherrypy.popargs('book_name')
class Book(object):
def __init__(self):
self.page = Page()
#cherrypy.expose
#cherrypy.tools.json_out()
def index(self, book_name):
return {"book name": book_name}
#cherrypy.expose
#cherrypy.tools.json_out()
def getdetails(self, book_name):
return {"details": bookname}
Page Class:
#cherrypy.popargs('page_number')
class Page(object):
#cherrypy.expose
#cherrypy.tools.json_out()
def index(self, book_name, page_number):
return {"book": book_name, "no": page_number}
# DOES NOT WORK AS EXPEXTED
# #cherrypy.expose
# #cherrypy.tools.json_out()
# def getdetails(self, book_name, page_number):
# return {"book": book_name, "no": page_number}
#cherrypy.expose
#cherrypy.tools.json_out()
def test(self, book_name):
return {"details": "some test"}
Service is the root class
if __name__ == '__main__':
cherrypy.quickstart(Service())
`
Related
Please find below sample source code, that returns :-
website home page, when auth service is not available,
default home page, when auth service available, but page service is
not available,
error page, when both services are not available,
user page, when all services are available
package tryeg
import scala.util._
/**
* Created by mogli on 6/6/17.
*/
class TrySample(val service : TryService) {
def homePageForUser(userId: String, secret: String): Try[Page] = {
val tryhomepage = for {
user <- service.authenticate(userId, secret)
homePage <- service.fetchHomePage(user)
} yield homePage
tryhomepage match {
case Failure(e: ServiceUnavailableException) =>
e.service match{
case "AuthService" =>
Try(WebsiteHomePage)
case "PageService" =>
Try(DefaultHomePage)
case _ =>
Try(ErrorPage)
}
case _ =>
tryhomepage
}
}
}
case class User(id: Long)
case class Page(title: String, content: String)
object DefaultHomePage extends Page("Welcome!", "This is your amazing Homepage!")
object WebsiteHomePage extends Page("Welcome!", "This is your amazing website")
object ErrorPage extends Page("Sorry!", "Unhandled Erro")
sealed class MyException(msg: String) extends Exception(msg, null)
case class UnknownUserException(userId: Long) extends MyException(s"User with id [$userId] is unknown.")
case class WrongSecretException(userId: Long) extends MyException(s"User with id [$userId] provided the wrong secret.")
case class ServiceUnavailableException(service: String) extends MyException(s"The Service [$service] is currently unavailable")
trait TryService {
def authenticate(userId: String, secret: String): Try[User]
def fetchHomePage(user: User): Try[Page]
}
Also, find below the sample unit test cases :-
package tryeg
import org.junit.runner.RunWith
import org.scalamock.scalatest.MockFactory
import org.scalatest.FlatSpecLike
import org.scalatest.junit.JUnitRunner
import scala.util.Try
/**
* Created by mogli on 6/6/17.
*/
#RunWith(classOf[JUnitRunner])
class TrySampleTest extends FlatSpecLike with MockFactory{
val user = User(123)
val tryuser = Try(user)
val userpage = Page("jbaba", "jbaba ka page")
val tryuserpage = Try(userpage)
"non happy path with authentication service not available" should "return website page" in {
val service = stub[TryService]
( service.authenticate(_, _) ).when("123", "secret") throws ServiceUnavailableException("AuthService")
val trySample = new TrySample(service)
val page = trySample.homePageForUser("123", "secret")
//page should be (Try(WebsiteHomePage))
println("non happy path for authentication service down ")
}
"non happy path with page service not available" should "return default home page" in {
val service = stub[TryService]
( service.authenticate(_, _) ).when("123", "secret") returns (tryuser)
( service.fetchHomePage(_) ).when(user) throws ServiceUnavailableException("PageService")
val trySample = new TrySample(service)
val page = trySample.homePageForUser("123", "secret")
//page should be (Try(DefaultHomePage))
println("non happy path for page service down ")
}
}
Now, the first test case is throwing below exception, but the expected result was Try(WebsiteHomePage)
tryeg.ServiceUnavailableException: The Service [AuthService] is currently unavailable
at tryeg.TrySampleTest$$anonfun$1.apply$mcV$sp(TrySampleTest.scala:31)
at tryeg.TrySampleTest$$anonfun$1.apply(TrySampleTest.scala:29)
at tryeg.TrySampleTest$$anonfun$1.apply(TrySampleTest.scala:29)
Your TryService stub is throwing an exception instead of returning a Failure.
Trying to do some TDD while learning the playframework:
class ContentFetching extends PlaySpec with BeforeAndAfter with MockFactory
{
private val service = ContentService
private val languages = List(Language(Some(1), "en", "English", "Placeholder"),
Language(Some(2), "de", "Deutsch", "Platzhalter")
)
"find" must
{
"fail if languageCode is invalid" in
{
val fakeRepository = mock[LanguageRepositoryTrait]
(fakeRepository.get _).expects().returning(languages)
fakeRepository.get must have length 3
service.find("fr") must be Result.NotFound
}
}
}
ContentService would call:
def fourOhFour() = NotFound(s"Oops, content could not be found")
yet the assertion service.find("fr") must be Result.NotFound won't compile. Why is that and how to test this then?
Here is the whole contentService (as requested) Sadly it extends Controller currently, because I found no other way to return an Action. Actually I use MVC, but a Service + repository-layer as well:
class ContentServiceComponent(languageRepository: LanguageRepositoryTrait, nodeRepository: NodeRepositoryTrait) extends Controller
{
def find(language: String) = Action
{
languageRepository.get().map(l => l.code).contains(language) match
{
case true => Ok(s"Homepage for $language")
case false => fourOhFour()
}
}
def fourOhFour() = NotFound(s"Oops, content could not be found")
}
object ContentService extends ContentServiceComponent(LanguageRepository, NodeRepository)
service.find("fr") from the Play controller returns a Result
Maybe you're comparing a Result with Result.Status type?
Can you use a play.api.helper?
status(of: Future[Result]) = Await.result(of, timeout.duration).header.status
Instead of
service.find("fr") must be Result.NotFound
Try something like this?
status(service.find("fr")) must be NOT_FOUND
NOT_FOUND is a play.api.http.Status value and just maps to the standard HTTP status code 404
find instead returns Action could return Option
def find(language: String): Option[String] =
{
languageRepository.get().map(l => l.code).contains(language) match
{
case true => Some(s"Homepage for $language")
case _ => None
}
}
So you cound handle it at Controller as follow:
def index(language:String) = Action{
ContentService.find(language) match{
case Some(content) => Ok(content)
case _ => NotFound(s"Oops, content could not be found")
}
}
and you could do test case something like this:
class ContentFetching extends PlaySpec with BeforeAndAfter with MockFactory
{
val languages = List(Language(Some(1), "en", "English",Placeholder"),Language(Some(2), "de", "Deutsch", "Platzhalter")
)
val languagesRepositoryMockHere = new LanguageRepositoryTrait{
override def get = languages //I don't know the implementations
}
"find" must
{
"fail if languageCode is invalid" in
{
private val service = new ContentServiceComponent(languagesRepositoryMockHere,nodeRepositoryMockHere)
service.find("fr") shouldBe None
}
}
}
This was not tested but could help for reference.
Cheers.
An example from «Learning concurrent programming in Scala»:
package org.learningconcurrency
import java.io.File
import java.util.concurrent.atomic.AtomicReference
import java.util.concurrent.{ConcurrentHashMap, ForkJoinPool, LinkedBlockingQueue}
import org.apache.commons.io.FileUtils
import scala.annotation.tailrec
/**
* Created by kaiyin on 1/19/16.
*/
import org.learningconcurrency.ch3.Ch3.execute
import scala.collection.convert.decorateAsScala._
object Issue {
sealed trait State
class Idle extends State
class Creating extends State
class Copying(val n: Int) extends State
class Deleting extends State
class Entry(val isDir: Boolean) {
val state = new AtomicReference[State](new Idle)
}
class FileSystem(val root: String) {
val rootDir = new File(root)
val files: collection.concurrent.Map[String, Entry] = new ConcurrentHashMap[String, Entry]().asScala
for (f <- FileUtils.iterateFiles(rootDir, null, false).asScala)
files.put(f.getName, new Entry(false))
def deleteFile(filename: String): Unit = {
files.get(filename) match {
case None =>
log(s"Path '$filename' does not exist!")
case Some(entry) if entry.isDir =>
log(s"Path '$filename' is a directory!")
case Some(entry) => execute {
if (prepareForDelete(entry))
if (FileUtils.deleteQuietly(new File(filename)))
files.remove(filename)
}
}
}
}
#tailrec private def prepareForDelete(entry: Entry): Boolean = {
val s0 = entry.state.get
s0 match {
case i: Idle =>
if (entry.state.compareAndSet(s0, new Deleting)) true
else prepareForDelete(entry)
case c: Creating =>
log("File is being created, cannot delete")
false
case c: Copying =>
log("File is being created, cannot delete")
false
case d: Deleting =>
false
}
}
def main(args: Array[String]) {
val fs = new FileSystem("/tmp")
fs.files.foreach(println _)
// Thread.sleep(500)
fs.deleteFile("test")
}
}
It just checks the state of one file and then deletes it, and the code looks like it should work, but after running it, the file I have created by touch /tmp/test is still there.
The problem is related to FileUtils.deleteQuietly(new File(filename)) line. According to the docs, deleteQuietly does the same as File.delete(), but instead of raising exceptions, it just returns true if the file was deleted and false if it was not.
Adding a debugging log would show that deleteQuietly is not working:
if (FileUtils.deleteQuietly(new File(filename))) {
println("File was deleted!")
files.remove(filename)
} else {
println("File was NOT deleted!")
}
It should print File was NOT deleted.
So what's wrong? Let's inspect the parameter you passed to deleteQuietly:
println((new File(filename)).exists()) // returns false
It seems that File didn't found your file. What is missing?
Since you are only providing the relative path test, you need also to provide the parent directory:
case Some(entry) => execute {
if (prepareForDelete(entry))
if (FileUtils.deleteQuietly(new File(rootDir, filename)))
files.remove(filename)
}
I'm having some trouble figuring out the best way create an easy way to test some of my DB centric application code. Maybe I am skewed from more OO languages, but what I am trying to do is start the application, seed the database, pass seeded data to the test, then clean up the database. I was trying to use before and after blocks, but have been running into all sorts of problem with delayedInit and other race conditions. In the docs you can use the setupData and deleteData, but it doesn't provide an opportunity to pass data to the actual tests. Is there any way this could be achieved?
Here is a sample of the wrapper I am using:
abstract class WithUserData extends WithApplication {
var user = null
override def around[T: AsResult](t: => T): Result = super.around {
setupData()
t
deleteData()
}
def setupData() {
Logger.info("Running Before")
val passwordInfo = PasswordInfo("bcrypt", "$2a$10$at8N/GZHKDbHLh6er.UsbOUjVqx.IGebO2Wc7EmmD2m4tOlin7EAG")
val u = User(new IdentityId("harrypotter#naytev.com", UsernamePasswordProvider.UsernamePassword), "Harry",
"Potter", "Harry Potter", Option("harrypotter#naytev.com"), None, AuthenticationMethod.UserPassword,
None, None, Some(passwordInfo), None, None, "", Subscription.free, None, None, None, List(), None)
User.save(u)
Logger.info(s"Before User is before saving : var ${user} --- variable ${u}")
user = u
Logger.info(s"variable user is ${user}")
}
def deleteData(): Unit ={
Logger.info(s"After User is -> $user")
Logger.info("Removing the user")
User.remove(user)
}
}
Then in my test, I would love to use it like this:
"with wrong password will not allow user to be logged in" in new WithUserData{
Logger.info(s"Running test 1 with User ${user}")
val fakeRequest = FakeRequest(POST, "/authenticate/userpass", FakeHeaders(), "").withFormUrlEncodedBody(("email" , user.email.get), ("password", "Blah"))
val request = route(fakeRequest).get
status(request) must equalTo(BAD_REQUEST)
}
The code above won't work and will give odd errors about user being null, even though the before is being run first. Is there any way for me to pass around a saved user object? I would love to not have to query the object every test. It seems like a lot of boiler plate and should be something handled in before and after.
Any help would be greatly appreciated!
Thanks,
Mike
Loock at http://docs.scala-lang.org/tutorials/FAQ/initialization-order.html
You can use something like cake pattern
case class User(id: BigInt, name: String)
trait UserRepositoryComponent {
def userLocator: UserLocator
trait UserLocator {
def getUser: User
def removeUser(user: User)
}
}
trait UserTestRepositoryComponent extends UserRepositoryComponent {
def userLocator = new UserTestLocator
class UserTestLocator extends UserLocator {
override def getUser: User = User(1, "test user")
override def removeUser(user: User): Unit = ()
}
}
trait UserRealRepositoryComponent extends UserRepositoryComponent {
def userLocator = new UserRealLocator
class UserRealLocator extends UserLocator {
override def getUser: User = User(1, "real user")
override def removeUser(user: User): Unit = ()
}
}
trait UserServiceComponent {
this: UserRepositoryComponent =>
def getUser: User = userLocator.getUser
def removeUser(user: User) = userLocator.removeUser(user)
}
trait WithUserData {
this: UserServiceComponent =>
println(getUser)
}
object Main extends App {
val userDataFake: WithUserData = new WithUserData with UserServiceComponent with UserTestRepositoryComponent
val userDataReal: WithUserData = new WithUserData with UserServiceComponent with UserRealRepositoryComponent
}
Or somthing like http://docs.scala-lang.org/tutorials/tour/implicit-parameters.html
I want to write a unit test to test my custom action builder.
Once I set the ActionWithSession as in instance in my test, how do I instantiate it like it would be in a controller?
How can I test for the edge cases if it redirects or returns with the Session?
class SessionAwareRequest[A](val context: MyContext, request: Request[A]) extends WrappedRequest[A](request)
class ActionWithSession #Inject()(siteConfig: SiteConfig, userService: UserService)
extends ActionBuilder[SessionAwareRequest] {
def invokeBlock[A](request: Request[A], block: (SessionAwareRequest[A]) => Future[Result]) = {
val session = loadSession(request)
if(session.isDefined) {
val result: Future[Result] = block(new SessionAwareRequest(session.get, request))
result.map(_.withCookies(CookieHelper.newSession(session.get)(request)))
}
else {
Future.successful(Results.Redirect(routes.MessagesController.show("error!")))
}
def loadSession(requestHeader: RequestHeader): Option[MySession] = {
...
Some(MySession(...))
else
None
}
}
If you're using Play 2.3, you should be able to utilize the PlaySpecification trait, which provides a call method to test Actions. Have a look at the Documentation, especially the section about "Unit Testing EssentialAction
".
Here's an artificial, minimal example based on the code you posted. It basically just checks whether the request headers contains a "foo" field and if so, returns OK together with an additional cookie "baz" that is added via the custom action builder. If the "foo" header is missing it returns BadRequest. Hope it helps.
import play.api.mvc._
import play.api.test.{FakeRequest, PlaySpecification}
import scala.concurrent.Future
class ActionSpec extends PlaySpecification {
case class MySession()
class SessionAwareRequest[A](val context: MySession, request: Request[A]) extends WrappedRequest[A](request)
object ActionWithSession extends ActionBuilder[SessionAwareRequest] {
def loadSession(requestHeader: RequestHeader): Option[MySession] = {
if (requestHeader.headers.get("foo").isDefined)
Some(MySession())
else
None
}
def invokeBlock[A](request: Request[A], block: (SessionAwareRequest[A]) => Future[Result]): Future[Result] = {
val session = loadSession(request)
if (session.isDefined) {
val result: Future[Result] = block(new SessionAwareRequest(session.get, request))
result.map(_.withCookies(Cookie("baz", "quux")))
} else {
Future.successful(Results.BadRequest)
}
}
}
"My custom action" should {
"return HTTP code 400 in case the request header does not contain a 'foo' field" in {
val foo = call(ActionWithSession { request =>
Results.Ok("Yikes")
}, FakeRequest())
status(of = foo) must beEqualTo(BAD_REQUEST)
cookies(of = foo).get("baz") must beNone
}
"return HTTP code 200 in case the request header does contain a 'foo' field" in {
val foo = call(ActionWithSession { request =>
Results.Ok("Yikes")
}, FakeRequest().withHeaders("foo" -> "bar"))
status(of = foo) must beEqualTo(OK)
cookies(of = foo).get("baz") must beSome
}
}
}