You have to pass the correct Content-Type for arguments to be parsed
(in this case, application/x-www-form-urlencoded).
On Tue, Aug 14, 2012 at 3:32 PM, bitcycle <
sean.m...@gmail.com> wrote:
> I'm trying to unit test my RESTful API.
>
> Here's my API and part of the test case:
>
>> class BaseHandler(tornado.web.RequestHandler):
>> def __init__(self, *args, **kwargs):
>> tornado.web.RequestHandler.__init__(self, *args, **kwargs)
>> self.log = self.application.log
>> self.db = self.application.db
>> class ProductHandler(BaseHandler):
>> @tornado.web.removeslash
>> def put(self, id = None, *args, **kwargs):
>> try:
>>
self.log.info("Handling PUT request")
>> if not id:
>> raise Exception('Object Id Required')
>> id = { '_id' : id }
>> new_values = dict()
>> name = self.get_argument('name', None)
>> description = self.get_argument('description', None)
>> if name:
>> new_values['name'] = name
>> if description:
>> new_values['description'] = description
>> self.db.products.update(id, new_values, safe = True)
>> except:
>> self.log.error("".join(tb.format_exception(*sys.exc_info())))
>> raise
>> class Application(tornado.web.Application):
>> def __init__(self, config_path, test = False, *args, **kwargs):
>> handlers = [
>> (r"/product/?(.*)", ProductHandler),
>> ]
>> settings = dict(debug=True)
>> tornado.web.Application.__init__(self, handlers, **settings)
>> self.log = logging.getLogger(__name__)
>> self.config = ConfigParser()
>> self.config.read(config_path)
>> self.mongo_connection = Connection(
>> host = self.config.get('mongo','host'),
>> port = self.config.getint('mongo','port'),
>> )
>> if test:
>> db_name = self.config.get('test', 'mongo.db')
>> else:
>> db_name = self.config.get('mongo', 'db')
>> self.log.debug("Using db: %s" % db_name)
>> self.db = self.mongo_connection[db_name]
>> class Test(AsyncHTTPTestCase):
>> def setUp(self):
>> clean_db(APP_CONFIG_PATH)
>> AsyncHTTPTestCase.setUp(self)
>> def tearDown(self):
>> clean_db(APP_CONFIG_PATH)
>> def get_app(self):
>> return Application(config_path = APP_CONFIG_PATH, test = True)
>> class CrudTest(Test):
>> def setUp(self):
>> GonzoTest.setUp(self)
>> self.URL = '/product'
>> self.log = logging.getLogger(__name__)
>> def test_product(self):
>> # ...
>> expected_product = dict()
>> expected_product['description'] = 'Some Other Description'
>> expected_product['name'] = 'Some Other Product Name'
>> self.log.debug("PUT request with expected field updates: %s" %
>> str(expected_product))
>> self.http_client.fetch(
>> "/".join([self.get_url(self.URL), new_product_id]),
>> self.stop,
>> method = "PUT",
>> body = urllib.urlencode(expected_product),
>> )
>> expected_product['id'] = new_product_id
>> response = self.wait()
>> self.assertEqual(response.code, 200)
>>
>> self.http_client.fetch(
>> "/".join([self.get_url(self.URL), new_product_id]),
>> self.stop,
>> )
>> response = self.wait()
>> self.assertEqual(response.code, 200)
>>
>> actual_product = json.loads(response.body)[0]
>> comparison_count = 0
>> for actual_product_key in actual_product:
>> for expected_product_key in expected_product:
>> if expected_product_key != actual_product_key:
>> continue
>> self.assertEqual(
>> expected_product[expected_product_key],
>> actual_product[actual_product_key]
>> )
>> comparison_count += 1
>> self.assertEqual(comparison_count, len(expected_product.keys()))
>> self.assertEqual(actual_product.keys(), expected_product.keys())
>
>
> Here's a dump of the unit test output:
>
>> F
>> ======================================================================
>> FAIL: test_product (test_app.CrudTest)
>> ----------------------------------------------------------------------
>> Traceback (most recent call last):
>> File "/home/bitcycle/git/gonzo/gonzo/test_app.py", line 114, in
>> test_product
>> actual_product[actual_product_key]
>> AssertionError: 'Some Other Description' != u'Some description of the acme
>> widget'
>> -------------------- >> begin captured logging << --------------------
>> test_app: INFO: Cleaning test db.
>> test_app: INFO: Using app.cfg
>> test_app: DEBUG: Dropping database: product_mgmt_testing
>> app: DEBUG: Using db: product_mgmt_testing
>> app: INFO: Handling POST request for a product
>> app: DEBUG: Getting arguments from POST data
>> app: INFO: Connecting to products collection
>> app: DEBUG: Creating product: name=Acme Widget, desc=Some description of
>> the acme widget
>> app: DEBUG: Inserting product as unpicklable json
>> app: DEBUG: oid: 502ad192907e131be8ba3574
>> app: DEBUG: 1 product(s) exist
>> root: INFO: 200 POST /product (127.0.0.1) 709.43ms
>> app: INFO: Handling GET request.
>> app: INFO: Locating search criteria
>> app: INFO: Using search_criterion: {'_id':
>> ObjectId('502ad192907e131be8ba3574')}
>> app: DEBUG: Found 1 products
>> root: INFO: 200 GET /product/502ad192907e131be8ba3574 (127.0.0.1) 2.76ms
>> test_app: DEBUG: Comparing expected={u'id': '502ad192907e131be8ba3574',
>> 'name': 'Acme Widget', 'description': 'Some description of the acme widget'}
>> and actual={u'description': u'Some description of the acme widget', u'id':
>> u'502ad192907e131be8ba3574', 'name': u'Acme Widget', u'create_ts':
>> u'2012-08-14 22:30:42'}
>> test_app: DEBUG: PUT request with expected field updates: {'description':
>> 'Some Other Description', 'name': 'Some Other Product Name'}
>> app: INFO: Handling PUT request for a product
>> app: DEBUG: Getting arguments from PUT data
>> app: DEBUG: Arguments: {}
>> app: DEBUG: Could not find name in arguments
>> app: DEBUG: Could not find description in arguments
>> app: INFO: Performing update with args: safe = True, id = {'_id':
>> u'502ad192907e131be8ba3574'}, new_values = {}
>> root: INFO: 200 PUT /product/502ad192907e131be8ba3574 (127.0.0.1) 0.84ms
>> app: INFO: Handling GET request.
>> app: INFO: Locating search criteria
>> app: INFO: Using search_criterion: {'_id':
>> ObjectId('502ad192907e131be8ba3574')}
>> app: DEBUG: Found 1 products
>> root: INFO: 200 GET /product/502ad192907e131be8ba3574 (127.0.0.1) 1.48ms
>
>
> And, here's my problem: the PUT handler isn't seeing the name or
> description arguments
>
> Can someone point me in the right direction?