Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AssertionError, altough the expected call looks same as actual call

I made a command in django which calls a function. That function does a django orm call:

def get_notes():
    notes = Note.objects.filter(number=2, new=1)
    return [x.note for x in notes]

I want to patch the actual lookup:

@mock.patch('Note.objects.filter', autospec=True)
def test_get_all_notes(self, notes_mock):
    get_notes()
    notes_mock.assert_called_once_with(number=2, new=1)

I get the following assertion error:

AssertionError: Expected call: filter(number=2, new=1)
Actual call: filter(number=2, new=1)

I search on google and stackoverflow for hours, but I still haven't a clue. Can anyone point me in the right direction, I think it might be an obvious mistake I'm making...

like image 715
Arjen Dijkstra Avatar asked Jul 28 '14 12:07

Arjen Dijkstra


1 Answers

AFAIK you can't use patch() like this. Patch target should be a string in the form package.module.ClassName. I don't know much about django but I suppose Note is a class so Note.objects.filter is not something you can import and hence use in patch(). Also I don't think patch() can handle attributes. Actually I don't quite understand why the patch works at all.

Try using patch.object() which is specifically designed to patch class attributes. It implies Note is already imported in your test module.

@mock.patch.object(Note, 'objects')
def test_get_all_notes(self, objects_mock):
    get_notes()
    objects_mock.filter.assert_called_once_with(number=2, new=1)

I've removed autospec because I'm not sure it will work correctly in this case. You can try putting it back if it works.

Another option might be to use patch() on whatever you get with type(Note.objects) (probably some django class).

As I've said I don't know much about django so I'm not sure if these things work.

like image 150
and Avatar answered Oct 31 '22 01:10

and