【问题标题】:Why does a call to a mocked object from within a generator fail to test correctly?为什么从生成器中调用模拟对象无法正确测试?
【发布时间】:2017-11-11 13:29:12
【问题描述】:

在下面的测试代码中,Generator 类包含两个方法,每个方法都调用 Counter 类的 next_count 方法。

这两个对next_count 的调用使用assert_called_with 进行了两个几乎相同的测试。生成器方法的测试失败。为什么?如何测试这个调用?

待测代码

generator.py

class Counter:
    def __init__(self):
        self.count = 1

    def next_count(self):
        self.count += 1
        return self.count


class Generator:
    def __init__(self):
        self.counter = Counter()

    def direct_call(self):
        self.counter.next_count()

    def iter_event(self):
        while True:
            yield self.counter.count
            self.counter.next_count()

测试模块

test_generator.py

import unittest
import unittest.mock

import generator


class Generator(unittest.TestCase):
    def setUp(self):
        p = unittest.mock.patch('generator.Counter')
        self.addCleanup(p.stop)
        self.mock_counter = p.start()

    def test_next_count_called_in_direct_call(self):  # Passes
        g = generator.Generator()
        g.direct_call()
        self.mock_counter.assert_called_with()

    def test_next_count_called_in_iter_event(self):  # Fails
        g = generator.Generator()
        count_gen = g.iter_event()
        next(count_gen)
        next(count_gen)
        self.mock_counter.next_count.assert_called_with()

【问题讨论】:

    标签: python python-3.x mocking generator python-unittest


    【解决方案1】:

    这与生成器无关。您测试了 2 个不同的东西,并且在两个测试中都测试了错误的东西。

    你的两个测试测试了不同的东西:

    def test_next_count_called_in_direct_call(self):  # Passes
        # ...
        self.mock_counter.assert_called_with()
    

    这会测试是否调用了 class。它确实被称为Counter()。请记住,mock_counter 模拟了 ,而不是实例。

    def test_next_count_called_in_iter_event(self):  # Fails
        # ...
        self.mock_counter.next_count.assert_called_with()
    

    这会测试是否调用了属性 Counter.next_count。这从未被调用,因为它是在实例上调用的。

    正确的测试是查看实例上的那个属性是否被调用:

    self.mock_counter.return_value.next_count.assert_called_with()
    

    self.mock_counter().next_count.assert_called_with()
    

    使用这是两个测试

    因为mock_counter 是类,所以最好将其命名为MockCounter

    以后,打印出你的模拟的mock_calls attribute;它会显示 被调用的。对于这两个测试,都会打印:

    [call(), call().next_count()]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-22
      • 1970-01-01
      • 1970-01-01
      • 2011-03-15
      • 1970-01-01
      • 2010-10-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多