0

Here is my class method:

def create(self, document=None):
 resp = self.db.document(None).post(params=document)
 if not resp.ok:
 logging.exception("Unknown response from Cloudant: %d" % resp.status_code)
 raise SystemError("Error creating document")
 if resp.ok and document.get("status") == "active":
 self.create_eda_document(resp.json().get("id"), document)
 return resp

And the test:

def test_create(self):
 self.klass.db = mock.MagicMock()
 self.klass.db.document = mock.MagicMock()
 post_mock = mock.MagicMock()
 d = {
 'ok': True,
 'id': '123',
 'rev': '1-bar'
 }
 resp_mock = mock.MagicMock(ok=True)
 resp_mock.__getitem__.side_effect = lambda name: d[name]
 post_mock.return_value = resp_mock
 post_mock.json.return_value = {"id": "123"}
 self.klass.db.document.return_value.post = post_mock
 self.klass.create_eda_document = mock.MagicMock(return_value={
 'ok': True,
 'id': '546',
 'rev': '1-baz'
 })
 resp = self.klass.create(
 document={
 'workflow': test_workflow(),
 'status': 'active',
 'name': 'Foo Bar',
 'account_id': 100,
 'created_at': party_like_its,
 'updated_at': party_like_its,
 'deleted_at': None
 }
 )
 print(resp)
 self.assertDictEqual(
 resp,
 {
 'ok': True,
 'id': '123',
 'rev': '1-bar'
 }
 )
 self.klass.create_eda_document.assert_called_once_with(
 '123',
 {
 'workflow': test_workflow(),
 'status': 'active',
 'name': 'Foo Bar',
 'account_id': 100,
 'created_at': party_like_its,
 'updated_at': party_like_its,
 'deleted_at': None
 }
 )

The final self.klass.created_eda_document.assert_called_once_with is failing because it actually isn't being called in the test. It's supposed to run because the document passed into the create method is "active", but the test says it's not. Not sure why it's not running

Update

Here's my test code

def test_create(self):
 self.klass.db = mock.MagicMock()
 self.klass.db.document = mock.MagicMock()
 post_mock = mock.MagicMock(ok=True)
 post_mock.return_value = {
 'id': '123',
 'ok': True,
 'rev': '1-bar'
 }
 self.klass.db.document.return_value.post = post_mock
 resp = self.klass.create(
 document={
 'workflow': test_workflow(),
 'status': 'active',
 'name': 'Foo Bar',
 'account_id': 100,
 'created_at': party_like_its,
 'updated_at': party_like_its,
 'deleted_at': None
 }
 )
 self.assertDictEqual(
 resp,
 {
 'ok': True,
 'id': '123',
 'rev': '1-bar'
 }
 )

And here's the error I am receiving:

Traceback (most recent call last):
 File "/Users/dmonsewicz/dev/autoresponders/tests/app/utils/test_workflows_cloudant.py", line 126, in test_create
 'deleted_at': None
 File "/Users/dmonsewicz/dev/autoresponders/app/utils/workflows_cloudant.py", line 40, in create
 if not resp.ok:
AttributeError: 'dict' object has no attribute 'ok'
asked Jul 29, 2014 at 2:08
3
  • You've mocked out the method that was supposed to call create_eda_document. Commented Jul 29, 2014 at 2:17
  • Could you provide an example of how to adjust my code so that everything is mocked out properly? Commented Jul 29, 2014 at 2:18
  • If you want to test create, don't mock it. Mock its inputs if you need to, but not the method itself. Commented Jul 29, 2014 at 2:19

1 Answer 1

1

First, you need to mock resp.json():

post_mock = mock.MagicMock()
post_mock.json.return_value = {"id": '123'}
self.klass.db.return_value.post = post_mock

Second, you don't actually want to do this:

self.klass.create = mock.MagicMock(return_value={
 'ok': True,
 'id': '123',
 'rev': '1-bar'
})

Since now you've mocked out the create method, which is what is supposed to call create_eda_document.

Also, you need to mock resp differently. It needs to be a dict-like object that also has an ok attribute. I think the best way to do that is to subclass dict:

class fakedict(dict):
 def __init__(*args, **kwargs):
 super(fakedict, self).__init__(*args, **kwargs)
 self.ok = None

...

post_mock = mock.MagicMock()
d = {
 'ok': True,
 'id': '123',
 'rev': '1-bar'
}
resp_mock = fakedict(d)
resp_mock.ok = True
post_mock.return_value = resp_mock

Your test will still pass without this change, though, because resp.ok will end up still being a non-Falsey value.

answered Jul 29, 2014 at 2:20
Sign up to request clarification or add additional context in comments.

7 Comments

Now when I run the self.klass.create the response coming back is <MagicMock name='mock.document().post()' id='4463821200'>
hmm... 1) Thanks so much for your help! 2) It's still failing with the same error. Let me update my question with the new code (including your help)
@dennismonsewicz I've fixed it somewhat. The problem is you're trying to treat resp like a dict with the self.assertDictEqual call, but it's not really a dict; normal dicts don't have an ok property.
@dennismonsewicz Actually, does it really even make sense to test resp in this case? You're mocking it anyway. To really test it, you'd need to say self.assertEquals(resp, resp_mock), which seems a bit strange.
It doesn't. I am updating my question with the latest bit of code and the error I am receiving
|

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.