首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何为TestCase设置一次“TestCase”。巨蟒。姜戈

如何为TestCase设置一次“TestCase”。巨蟒。姜戈
EN

Stack Overflow用户
提问于 2018-08-06 15:06:23
回答 1查看 2.6K关注 0票数 2

下面是示例测试:

代码语言:javascript
运行
复制
import a
import b
import c

import mock
from django.test import TestCase

@mock.patch.object(a, "method_a")
@mock.patch.object(b, "method_b")
@mock.patch.object(c, "method_c")
class SomeTestCase(TestCase):

    def setUp(self):
        # I want to set mock_method_a.return_value = 1 once here (or not here, but once)
        pass

    def test_one(self, mock_method_a, mock_method_b, mock_method_c):
        mock_method_a.return_value = 1
        mock_method_b.return_value = 2
        pass  # some test stuff

    def test_two(self, mock_method_a, mock_method_b, mock_method_c):
        mock_method_a.return_value = 1
        mock_method_b.return_value = 2
        pass  # some test stuff

    def test_three(self, mock_method_a, mock_method_b, mock_method_c):
        mock_method_a.return_value = 1
        mock_method_b.return_value = 2
        pass  # some test stuff

Queston

如何避免在每次测试中设置"return_value“的重复代码?

我期望在"setUp“方法或类似的东西。

有可能吗?

PS:模拟版本mock==1.3.0,django版本Django==1.8.4

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-08-06 15:19:51

您可以在return_value装饰器中设置@mock.patch.object()

代码语言:javascript
运行
复制
@mock.patch.object(c, "method_c", return_value=3)
@mock.patch.object(b, "method_b", return_value=2)
@mock.patch.object(a, "method_a", return_value=1)
class SomeTestCase(TestCase):
    def test_one(self, mock_method_a, mock_method_b, mock_method_c):
        # do test stuff, return values have been set

    def test_two(self, mock_method_a, mock_method_b, mock_method_c):
        # do test stuff, return values have been set

    def test_three(self, mock_method_a, mock_method_b, mock_method_c):
        # do test stuff, return values have been set

(注意:在用@mock.patch进行装饰时,装饰器是自下而上应用的,因此要传递mock_method_a作为第一个参数,您需要将装饰器放在最接近类定义的位置)。

return_value关键字参数传递给mock.patch.object()构造函数。见 documentation

patch()一样,patch.object()使用任意关键字参数来配置它创建的模拟对象。

documentation

Mock采用几个可选参数来指定Mock对象的行为:

  • ..。
  • return_value:调用模拟时返回的值。默认情况下,这是一个新的Mock (创建于第一次访问)。请参见return_value属性。

如果您还想避免在测试用例之外设置模拟,或者不喜欢每个测试函数的附加参数,那么您还可以在setUp方法中创建修补程序,然后在测试结束时通过通过 method注册回调来再次删除该修补程序。

通过调用 methods,为每个测试应用补丁程序,后者返回新的模拟对象:

代码语言:javascript
运行
复制
class SomeTestCase(TestCase):    
    def setUp(self):
        patcher_method_a = mock.patch.object(a, "method_a")
        self.mock_method_a = patcher_method_a.start()
        self.mock_method_a.return_value = 1

        patcher_method_b = mock.patch.object(b, "method_b")
        self.mock_method_b = patcher_method_b.start()
        self.mock_method_b.return_value = 2

        patcher_method_c = mock.patch.object(c, "method_c")
        self.mock_method_c = patcher_method_c.start()
        self.mock_method_c.return_value = 3

        # when the test is done, stop **all** patchers
        self.addCleanup(mock.patch.stopall)

    def test_one(self):
        # use self.mock_method_a, etc.

    def test_two(self, mock_method_a, mock_method_b, mock_method_c):
        # use self.mock_method_a, etc.

    def test_three(self, mock_method_a, mock_method_b, mock_method_c):
        # use self.mock_method_a, etc.

注意,mock.patch.stopall()方法将停止所有已启动的模拟修补程序。您还可以传递每个修补程序的.stop属性:

代码语言:javascript
运行
复制
self.addCleanup(patcher_method_a.stop)
self.addCleanup(patcher_method_b.stop)
self.addCleanup(patcher_method_c.stop)

如果您必须创建许多这样的设置,您可以创建一个助手函数来处理重复的部分:

代码语言:javascript
运行
复制
def setup_object_patch(testcase, object, target, return_value, attrname=None):
    patcher = mock.patch.object(object, target)
    mock = patcher.start()
    mock.return_value = return_value
    setattr(testcase, attrname or f'mock_{target}', mock)
    testcase.addCleanup(patcher.stop)

也许可以在映射的循环中使用这一点:

代码语言:javascript
运行
复制
def setUp(self):
    mocks = {
        # attribute name on test -> object, target, return_value
        'mock_method_a': (a, 'method_a', 1),
        'mock_method_b': (b, 'method_b', 2),
        'mock_method_c': (c, 'method_c', 3),
    }
    for attrname, params in mocks.items():
        setup_object_patch(*params, attrname=attrname)

patcher.start()方法中的TestCase.setUp()方法使继承更容易使用,其中一个基本测试用例被用作多个测试用例的基础,所有这些测试用例都使用相同的共享模拟设置。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51710660

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档