python - 为什么从生成器内调用模拟对象无法正确测试?

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

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

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

待测代码

生成器.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()

最佳答案

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

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

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

这测试是否被调用。它确实被称为 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你的 mock ;它会显示称为什么。对于这两个测试,都会打印:

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

关于python - 为什么从生成器内调用模拟对象无法正确测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47238410/

相关文章:

python - 使用 Elixir、erlport 和 Python 2.7.9,收到数量错误

Python:使用多个文本文件时如何仅使用 1 列?

python - 在 Python 中使用 PMML 模型

testing - RequestMock 返回 222 状态代码,没有正文

python - 如何加载经过训练的 TensorFlow 模型以使用不同的批量大小进行预测?

python - IPython 笔记本 : using quotes (') and dollar($) to pass string variable as argument to python script in command-line(!) | eg: abc.py -arg1 ' $var1'

python - 如何在 py.test 运行结束时获取 TestReports 列表?

python - Python 命令提示符中的制表符/缩进错误

java - 相当于mockito中 spy 的Answers.RETURNS_DEEP_STUBS

java - 如何在 Spring 中使用 Mock 为 CommonsMultipartFile 编写单元测试