简体   繁体   English

比较模拟对象中的生成器对象。assert_has_calls

[英]compare generator objects within mock.assert_has_calls

I'm writing a unit test for a function that will confirm that a function called within it is called with the correct arguments. 我正在为一个函数编写单元测试,该测试将确认使用正确的参数调用其中的函数。 The problem is that one of the arguments is a generator. 问题在于参数之一是生成器。

Is there a way to compare the contents of the generator that fn is called with using assert_has_calls ? 有没有一种方法可以使用assert_has_calls比较调用fn的生成器的内容? An example of the behavior that I'm looking for is exhibited in 'AssertSequenceEqual.' 我要寻找的行为的一个示例在“ AssertSequenceEqual”中进行了展示。 As it is, test_use_fn fails because the generator objects that it is comparing are different. 实际上,由于要比较的生成器对象不同,因此test_use_fn失败。

import mock

def fn(entries):
    pass

def use_fn(entries, convert=lambda x: x):
    entries = (convert(entry) for entry in entries)
    entries = fn(entries)
    entries = fn(entries)

@mock.patch('fn')
def test_use_fn(self, mock_fn):
    mock_fn.return_value = 'baz'
    entries = ['foo', 'bar']
    use_fn(entries)
    call_1 = mock.call((entry for entry in entries))
    call_2 = mock.call('baz')
    mock_fn.assert_has_calls([call_1, call_2])

You can use call_args_list https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.call_args_list 您可以使用call_args_list https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.call_args_list

I assume that you would check if every items of the generators are the same. 我假设您将检查生成器的每个项目是否相同。 I write a assertEqualGenerators() method of the test case class that do the work (if the arguments are not generators use standard assertEqual() ). 我编写了完成该工作的测试用例类的assertEqualGenerators()方法(如果参数不是生成器,则使用标准的assertEqual() )。 The module file name is mock_generators.py and you must use mock_generators.fn to patch fn . 模块文件名是mock_generators.py ,您必须使用mock_generators.fn修补fn The last trick is the call object arguments: take a look to https://docs.python.org/3/library/unittest.mock.html#unittest.mock.call.call_list for the dettails of how fetch the data (in your case the first element is what you need). 最后一个技巧是call对象参数:看一下https://docs.python.org/3/library/unittest.mock.html#unittest.mock.call.call_list了解如何获取数据的细节(在您的案例,第一个要素就是您所需要的)。

import unittest
from unittest import mock

def fn(entries):
    pass

def use_fn(entries, convert=lambda x: x):
    entries = (convert(entry) for entry in entries)
    entries = fn(entries)
    entries = fn(entries)

class MyTestCase(unittest.TestCase):

    def assertEqualGenerators(self,a,b):
        try:
            for x,y in zip(a,b):
                self.assertEqual(x, y)
        except TypeError:
            self.assertEqual(a, b)

    @mock.patch("mock_generators.fn")
    def test_use_fn(self, mock_fn):
        mock_fn.return_value = 'baz'
        entries = ['foo', 'bar']
        use_fn(entries)
        calls = [mock.call((entry for entry in entries)),
                    mock.call('baz')]
        self.assertEqual(len(calls), mock_fn.call_count)
        for a,b in zip(mock_fn.call_args_list,calls):
            self.assertEqualGenerators(a[0],b[0])


if __name__ == '__main__':
    unittest.main()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM