Python 3.6初学者:为什么为assert_Called_once_with获得一个空白的AssertionError(单元测试和模拟)

时间:2019-06-22 18:36:49

标签: python unit-testing mocking

嗨,我是Python的新手,我正在尝试运行以下模拟单元测试。任何帮助将不胜感激,在此先感谢您!

我有一个LeadsConsumer类(Leadsconsumer模块的类),我想对其方法_process_lead进行单元测试。

from .helper import dynamo_helpers

class LeadsConsumer:

    def __init__(self):
        self._dynamodb = dynamo_helpers.Dynamo(AWS_RUNTIME_REGION, ENVIRONMENT, VERTICAL)

    def _process_lead(self, _lead):
        role_set = self._dynamodb.get_role_set(_lead.getPartner_id())
        if role_set is None:
            role_set = self._dynamodb.create_partner(_lead)
        if role_set['is-partner'] is True:
            return

        user = self._dynamodb.get_user(_lead.getEmail())
        if user is None:
            user = self._dynamodb.create_user(_lead)
        else:
            user = self._dynamodb.update_user(_lead)

单元测试如下:

class LeadsConsumerTest(TestCase):

    @mock.patch('src.leads_consumer.dynamo_helpers.Dynamo')
    def test_process_lead_new_lead(self, mock_dynamo_class):
        # given
        mock_dynamo_instance = mock_dynamo_class.return_value
        mock_dynamo_instance.get_role_set.return_value = None
        mock_dynamo_instance.create_partner.return_value = self._given_role_set(False)
        mock_dynamo_instance.get_user.return_value = None
        mock_dynamo_instance.create_user.return_value = None

        _leads_consumer = LeadsConsumer()
        _lead = self._given_lead(False)

        # when
        _leads_consumer._process_lead(_lead)

        # then
        assert mock_dynamo_instance.get_role_set.assert_called_once_with(_lead.getPartner_id())
        assert mock_dynamo_instance.create_partner.assert_called_once()
        assert mock_dynamo_instance.get_user.assert_called_once()
        assert mock_dynamo_instance.create_user.assert_called_once_with(_lead)

运行此测试时,出现以下AssertionError:

in test_process_lead_new_lead
assert mock_dynamo_instance.get_role_set.assert_called_once_with(_lead.getPartner_id())
AssertionError

空白的AssertionError(没有任何关于错误的解释)有点让我感到困惑。如果我改变

assert mock_dynamo_instance.get_role_set.assert_called_once_with(_lead.getPartner_id())

assert mock_dynamo_instance.get_role_set.assert_called_once_with("foobar", _lead.getPartner_id())

我明白了

AssertionError: Expected call: get_role_set('foobar', '1000000')
Actual call: get_role_set('1000000')

据我了解,这是可以预料的。但是,如果我按照上面的原始方法进行测试,为什么还要得到一个AssertionError? 我不明白修改后的测试显示已使用('foobar','1000000')调用了方法get_role_set。因此,如果我省略“ foobar”,为什么测试不会没有错误地通过? (如果我注释掉其他断言,则在测试的最后一行中实际上会出现相同的错误。)

有人可以告诉我我在做什么错吗?另外,对于菜鸟代码中其他缺陷的提示将不胜感激。 谢谢。

1 个答案:

答案 0 :(得分:1)

您在这里混淆了两种语法。 assert是用于正则表达式的命令;如果表达式不正确,则会引发异常。

assert_called_once_with是Mock对象提供的方法,如果失败则再次引发AssertionError,否则返回None。

因此,这里有两个断言。 assert_called_once_with调用的结果为None,这当然是错误的;因此您会从assert语句中获得一个AssertionError。

解决方案是简单地删除所有assert关键字,而只保留assert_called_onceassert_called_once_with方法调用。