how to unittest the template variables passed to jinja2 template from webapp2 request handler

google-app-engine, jinja2, unit-testing, webapp2, wsgi

Solution

You can mock `BaseHandler.render_template` method and test its parameters.

See this question for a list of popular Python mocking frameworks.

Problem

I'm trying to test my webapp2 handlers. To do this, I thought it would be a good idea to send a request to the handler e.g.: ``` request = webapp2.Request.blank('/') # Get a response for that request. response = request.get_response(main.app) ``` The problem is, response is mostly just a bunch of HTML etc. I want to look at what was passed to my jinja2 template from the handler before it was turned into HTML. I want my test to get at the state within the handler class code. I wan't to be able to see what certain variables looked like in the response handler, and then I want to see what the dict templates looks like before it was passed to render_to_response() I want to test these variables have the correct values. Here is my test code so far, but I'm stuck because response = request.get_response() just gives me a bunch of html and not the raw variables. ``` import unittest import main import webapp2 class DemoTestCase(unittest.TestCase): def setUp(self): pass def tearDown(self): pass def testNothing(self): self.assertEqual(42, 21 + 21) def testHomeHandler(self): # Build a request object passing the URI path to be tested. # You can also pass headers, query arguments etc. request = webapp2.Request.blank('/') # Get a response for that request. response = request.get_response(main.app) # Let's check if the response is correct. self.assertEqual(response.status_int, 200) self.assertEqual(response.body, 'Hello, world!') if __name__ == '__main__': unittest.main() ``` and here is my handler: ``` class HomeHandler(BaseHandler): def get(self, file_name_filter=None, category_filter=None): file_names = os.listdir('blog_posts') blogs = [] get_line = lambda file_: file_.readline().strip().replace("<!--","").replace("-->","") for fn in file_names: with open('blog_posts/%s' % fn) as file_: heading = get_line(file_) link_name = get_line(file_) category = get_line(file_) date_ = datetime.strptime(fn.split("_")[0], "%Y%m%d") blog_dict = {'date': date_, 'heading': heading, 'link_name': link_name, 'category': category, 'filename': fn.replace(".html", ""), 'raw_file_name': fn} blogs.append(blog_dict) categories = Counter(d['category'] for d in blogs) templates = {'categories': categories, 'blogs': blogs, 'file_name_filter': file_name_filter, 'category_filter': category_filter} assert(len(file_names) == len(set(d['link_name'] for d in blogs))) self.render_template('home.html', **templates) ``` and here is my basehandler: ``` class BaseHandler(webapp2.RequestHandler): @webapp2.cached_property def jinja2(self): return jinja2.get_jinja2(app=self.app) def render_template(self, filename, **kwargs): #kwargs.update({}) #TODO() datastore caching here for caching of (handlername, handler parameters, changeable parameters, app_upload_date) #TODO() write rendered page to its own html file, and just serve that whole file. (includes all posts). JQuery can show/hide posts. self.response.write(self.jinja2.render_template(filename, **kwargs)) ``` Perhaps I have got the wrong idea of how to do unit testing, or perhaps I should have written my code in a way that makes it easier to test? or is there some way of getting the state of my code? Also if someone were to re-write the code and change the variable names, then the tests would break.

Original source

Related problems