andy boot
andy boot

Reputation: 11757

tornado testing @tornado.web.authenticated

I'm trying to test tornado using AsyncHTTPTestCase. I want to test handlers marked with the @tornado.web.authenticated annotation. Because this handler requires authentication we must login first or somehow fool it in thinking we are authenticated in our test code

class HandlerToTest(BaseHandler):
  @tornado.web.authenticated
  def get(self):
    self.render("hello.html", user=self.get_current_user() )

According to this article we can fudge the cookies. I have got this working but according to Ben Darnell tornado maintainer this is not recommended. Ben recommends using the CookieLib module but that requires the 'info' part of the response which we don't have.

Another blog post suggests mocking the get_current_user() call using mox. However I can not get the sample code in the blog working.

So my question is: What is the best way of testing the handlers marked as authenticated? And can someone point me to a sample application?

Upvotes: 4

Views: 3806

Answers (3)

andy boot
andy boot

Reputation: 11757

Eventually got Mocks working. Don't know if this is the 'best way' but it might be useful to someone in the future. This code tests 2 handlers and mocks the get_current_user() call generated by @tornado.web.authenticated:

# encoding: utf-8
import os, os.path, sys
import tornado.web
import tornado.testing
import mox

class BaseHandler(tornado.web.RequestHandler):
    def get_login_url(self):
        return u"/login"

    def get_current_user(self):
        user_json = self.get_secure_cookie("user")
        if user_json:
            return tornado.escape.json_decode(user_json)
        else:
            return None

class HelloHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self):
        self.render("protected.html")


class Protected(tornado.web.RequestHandler):
    def get_current_user(self):
        # get an user from somewhere
        return "andy"

    @tornado.web.authenticated
    def get(self):
        self.render("protected.html")


class TestAuthenticatedHandlers(tornado.testing.AsyncHTTPTestCase):
    def get_app(self):
        self.mox = mox.Mox()
        app = tornado.web.Application([
            (r'/protected', Protected),
            (r'/hello', HelloHandler)
        ])
        return app

    def tearDown(self):
        self.mox.UnsetStubs()
        self.mox.ResetAll()

    def test_new_admin(self):
        self.mox.StubOutWithMock(Protected, 'get_current_user', use_mock_anything=True)
        Protected.get_current_user().AndReturn("test_user")
        self.mox.ReplayAll()
        resp = self.fetch('/protected')
        self.assertEqual(resp.code, 200)
        self.mox.VerifyAll()

    def test_hello_page(self):
        self.mox.StubOutWithMock(HelloHandler, 'get_current_user', use_mock_anything=True)
        HelloHandler.get_current_user().AndReturn("test_user")
        self.mox.ReplayAll()
        resp = self.fetch('/hello')
        self.assertEqual(resp.code, 200)
        self.assertIn( "Hello", resp.body )
        self.mox.VerifyAll()

Upvotes: 5

hh-hornet
hh-hornet

Reputation: 1

In my case simply works:

BaseHandler.get_current_user = lambda x: {'username': 'user', 'email': '[email protected]'}

Upvotes: -2

andy boot
andy boot

Reputation: 11757

This Torando utils library also allows you to test authenticated handlers: tornado_utils/http_test_client.py

Upvotes: 0

Related Questions