Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mocks returned by QuerySetMock should return self when QuerySet-generating methods are called #15

Closed
boydjj opened this issue Feb 8, 2013 · 5 comments

Comments

@boydjj
Copy link
Contributor

boydjj commented Feb 8, 2013

For complicated views, where several QuerySet-generating methods (e.g., filter() or order_by()) are called, the SharedMock returned by QuerySetMock breaks application code. Here's an example::

In [1]: from django.conf import settings; settings.configure()

In [2]: from mock_django.query import QuerySetMock

In [3]: class RouteModel(object): pass

In [4]: route_mgr = QuerySetMock(RouteModel, 1, 2, 3)

In [5]: route_mgr.filter() # this works fine, but it returns a generator

In [6]: route_mgr.filter().order_by() # failure, because generators aren't what we need
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-6-f57426e07858> in <module>()
----> 1 route_mgr.filter().order_by() # fail

AttributeError: 'generator' object has no attribute 'order_by'

So mocking out a QuerySet with a SharedMock fails in any chain-calling application code.

I must admit I'm not quite clear on why this is happening at the moment, because at least on first glance it seems like self should already be returned. But I'm considering a patch that would ensure that such methods always return self, at least for QuerySetMock. Would such a patch be useful to folks? Is there something I'm missing in my use that would allow me to fix the issue otherwise? And, finally, is there a use case I'm not considering where such a patch would break the current behavior?

@bullfinch3000
Copy link

I encountered the same problem and managed to solve it, at least for my use case, in 50f7e70

@boydjj
Copy link
Contributor Author

boydjj commented Aug 20, 2013

Sorry it's taken a while to get back to this. Your change breaks the existing tests:

$ python runtests.py 
.........................F......
======================================================================
FAIL: Each QuerySet-returning method's return value is unique.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/jboyd/Projects/mock-django/tests/mock_django/query/tests.py", line 27, in test_qs_generator_inequality
    self.assertNotEquals(qs.all(), qs.filter())
AssertionError: <SharedMock name='mock.filter' id='4543475664'> == <SharedMock name='mock.filter' id='4543475664'>

----------------------------------------------------------------------
Ran 32 tests in 0.356s

@boydjj
Copy link
Contributor Author

boydjj commented Aug 23, 2013

@henrikalmer If you're currently using your solution, can you take a look at my latest PR and verify that your uses still pass? Instead of just returning a new iterator, I return a new copy of the QuerySetMock for most QuerySet-returning methods.

@boydjj boydjj closed this as completed Aug 24, 2013
@bullfinch3000
Copy link

@boydjj I've tried the latest PR and it seems to work with well, with one exception. I need to be able to add custom queryset returning methods that correspond to methods on a custom manager. I've added a settings variable to do this locally and if you wish I could submit a pull request.

@hugotox
Copy link

hugotox commented Oct 29, 2013

I solved this issue in my code by using mock and return_value:

route_mgr.filter.return_value = Mock()
route_mgr.filter.return_value.order_by = Mock()
route_mgr.filter.return_value.order_by.return_value = QuerySetMock(None)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants