Python:测试方法是在另一个方法中调用的

时间:2014-07-29 02:08:45

标签: python unit-testing

这是我的班级方法:

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

测试:

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
        }
    )

最终的self.klass.created_eda_document.assert_called_once_with失败了,因为它实际上并未在测试中被调用。它应该运行,因为传入create方法的文件是“活跃的”#34;但是测试表明它没有。不知道为什么它没有运行

更新

这是我的测试代码

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'
        }
    )

这是我收到的错误:

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'

1 个答案:

答案 0 :(得分:1)

首先,您需要模拟resp.json()

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

其次,你实际上并不想这样做:

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

从现在开始,您已经嘲笑了create方法,该方法应该调用create_eda_document

此外,您需要以不同方式模拟resp。它必须是一个类似于dict的对象,它也具有ok属性。我认为最好的方法是继承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

但是,如果没有此更改,您的测试仍会通过,因为resp.ok最终仍然是非Falsey值。