Python 单元测试:为什么在测试中需要“mock”?

use*_*632 0 python django unit-testing mocking

我不明白为什么我们需要mock在一些测试用例中,特别是像下面这样:

主要.py

import requests

class Blog:
    def __init__(self, name):
        self.name = name

    def posts(self):
        response = requests.get("https://jsonplaceholder.typicode.com/posts")

        return response.json()

    def __repr__(self):
        return '<Blog: {}>'.format(self.name)
Run Code Online (Sandbox Code Playgroud)

测试.py

import main

from unittest import TestCase
from unittest.mock import patch


class TestBlog(TestCase):
    @patch('main.Blog')
    def test_blog_posts(self, MockBlog):
        blog = MockBlog()

        blog.posts.return_value = [
            {
                'userId': 1,
                'id': 1,
                'title': 'Test Title,
                'body': 'Far out in the uncharted backwaters of the unfashionable end of the western spiral arm of the Galaxy\ lies a small unregarded yellow sun.'
            }
        ]

        response = blog.posts()
        self.assertIsNotNone(response)
        self.assertIsInstance(response[0], dict)
Run Code Online (Sandbox Code Playgroud)

这段代码来自这个博客

我很好奇的是,正如您在测试代码中看到的那样,测试代码设置blog.posts.return_value为一些理想的对象(dict)。

但是,我认为这种模拟是没有用的,因为这段代码只是测试用户return_value在测试代码中正确设置的情况,而不是真正的Blog“对象真正返回的内容”。

我的意思是,即使我在 main.py 中返回真正的函数posts测试代码也会通过所有测试,因为用户在测试代码中设置正确!1areturn_value

无法理解为什么需要这种测试。

你们能解释一下吗?

Gia*_*tta 5

这个例子本身是没有用的。事实上,它嘲笑了错误的事情。应该使用模拟来代替服务/数据库等。

例如:模拟requests.get就完全没问题:您已经假设该requests库可以工作,因此在测试期间您可以避免执行 HTTP 调用并简单地返回页面内容。通过这种方式,您将测试该posts方法的逻辑,而不考虑其requests作用(即使在本例中它非常简单)。

当然,模拟您正在测试的类是没有意义的。你应该模拟它的依赖关系!