【问题标题】:Mocking a function that is invoked twice with different arguments模拟使用不同参数调用两次的函数
【发布时间】:2016-04-18 23:57:09
【问题描述】:

假设我有以下功能:

def function_to_test(context):
    list_of_invocations = [ func('arg%s' % number) for number in [1,2]]
    email_one = list_of_invocations[0].render(context)
    email_two = list_of_invocations[1].render(context)
    instance = class_to_mock(email_one, arg_1, arg_2)  
    instance.method_for_class(email_two, 'text/html')
    instance.send()

@mock.patch('app.foo.class_to_mock')
@mock.patch('app.foo.func')
def test_render_and_send_email(self, func_mock, mock_to_class):
    render_method = mock.Mock()
    render_method.return_value = mock.Mock()

    class_method = mock.Mock()
    class_method.return_value = mock.Mock()

    func_mock.return_value = mock.MagicMock(render=render_method)
    mock_to_class.return_value = mock.Magic(method_for_class=class_method)
    function_to_test('context goes heres')
    self.assertEqual(func_mock.call_count, 2)
    self.assertEqual(render_method.call_count, 2)
    self.assertEqual(mock_to_class.call_count, 1)
    self.assertEqual(method_class.call_count,1)

我正在尝试使用模拟测试此功能,但我无法决定如何测试它。想到的两个选项是使用side_effectassert_has_calls。这是我正在尝试做的事情。

  • 我想确保func 被调用了两次。 (完成)
  • 我想为每个func 调用创建一个模拟(未完成)
  • 我想确保渲染被调用了两次。 (完成)
  • 我想确保class_to_mock 是用email_one 调用的 我需要一个模拟 email_oneemail_two(未完成)

测试会是这样的

`mock_to_class.assert_called_once_with(*MOCK EMAIL ONE*,'one', 'two')`
  • 我希望 '''method_for_class''' 看起来像这样 (未完成)

    class_method.assert_called_once_with(*MOCK EMAIL TWO*, 'text/html')

希望这是有道理的。基本上,我需要来自func 的两个不同调用来确保class_to_mockmethod_for_class 中有参数。

【问题讨论】:

    标签: python unit-testing mocking python-unittest magicmock


    【解决方案1】:

    您可以在@patch.object 中使用new 属性:

    email_one=Mock()
    email_two=Mock()
    
    func_call_count = 0
    def my_func_mock():
        global func_call_count
        func_call_count += 1
    
        if func_call_count == 1:
            do_invocation_1()
    
        if func_call_count == 2:
            do_invocation_2()
    
    def do_invocation_1():
        return [email_one, email_two]
    
    def do_invocation_2():
        return [email_one, email_two]
    
    @mock.patch('app.foo.class_to_mock')
    @mock.patch('app.foo.func', new=my_func_mock)
    def test_render_and_send_email(self, func_mock, mock_to_class):
        render_method = mock.Mock()
        render_method.return_value = mock.Mock()
    
        class_method = mock.Mock()
        class_method.return_value = mock.Mock()
    
        func_mock.return_value = mock.MagicMock(render=render_method)
        mock_to_class.return_value = mock.Magic(method_for_class=class_method)
        function_to_test('context goes heres')
        self.assertEqual(func_call_count, 2) # Use the func_call_count instead
        self.assertEqual(render_method.call_count, 2)
        mock_to_class.assert_called_once_With(email_one, email_two) # Now you can assert it is called once with email_one & two
        self.assertEqual(method_class.call_count,1)
    

    【讨论】:

      猜你喜欢
      • 2019-05-22
      • 1970-01-01
      • 2022-08-23
      • 2022-08-17
      • 1970-01-01
      • 1970-01-01
      • 2017-04-16
      • 2013-01-21
      • 2022-01-04
      相关资源
      最近更新 更多