pythonpython-requestspyramidpython-unittestcornice

Unittesting Pyramid/Cornice resource with query string in a URL


I have Pyramid/cornice resource, that requires a ?query=keyword in end of the url. But I don't know how to add this in a pyramid's dummyRequest object. Code works perfectly on browser and I will get correct response when using this url to get stuff: *url*/foo?query=keyword.

My class/resource is defined like this:

@resource(path='/bar/search/foo')
class SearchFooResource(object):
    def __init__(self, request):
        self.request = request

    @view(renderer='json')
    def get(self):
        #get query string, it's a tuple
        req = self.request.GET.items()
        #do stuff with req

Now req should contain the all the query string 'stuffs' in a list that contains them as a tuple's, for example: [('query', 'bar'),('query', 'asd')]. But how do I make unittest to this resource? I can't seem to add anything to self.request.GET.items() method. When running unittest req is empty, and I will get this error: AttributeError: 'list' object has no attribute 'items'.

My current unittest:

def test_passing_GetFooBaarResource(self):
    request = testing.DummyRequest()
    request.GET = [('query', 'keyword')]    
    info = SearchFooResource.get(SearchFooResource(request))

    self.assertEqual(info['foo'], 'baar')

Solution

  • In addition to what @matino has suggested, you can just use a plain dictionary (instead of a list of tuples you tried).

    def test_passing_GetFooBaarResource(self):
        request = testing.DummyRequest()
        request.GET = {'query': 'keyword'}   
        info = SearchShowResource.get(SearchShowResource(request))
    
        self.assertEqual(info['foo'], 'baar')
    

    This will work in uncomplicated cases where you don't have multiple parameters with the same name (/someurl?name=foo&name=baz&name=bar).

    If you need to test those more complicated queries you can replace your DummyRequest's GET attribute with a WebOb MultiDict

    from webob.multidict import MultiDict
    
    def test_passing_GetFooBaarResource(self):
        request = testing.DummyRequest()
        request.GET = MultiDict([('query', 'foo'), ('query', 'bar'), ('query', 'baz')])    
        info = SearchShowResource.get(SearchShowResource(request))
    
        self.assertEqual(info['foo'], 'baar')
    

    Then, normally, in your actual view method, if you need to handle multiple parameters with the same name you use request.GET.getall('query') which should return ['foo', 'bar', 'baz'].

    In simpler cases you can just use request.GET['query'] or request.GET.get('query', 'default'). I mean, your use of request.GET.items() is a bit unusual...