【问题标题】:Mocking functions from object created by context manager来自上下文管理器创建的对象的模拟函数
【发布时间】:2019-06-06 13:35:09
【问题描述】:

我有以下模块,我正在尝试为其编写单元测试。

import myModuleWithCtxMgr

def myFunc(arg1):
    with myModuleWithCtxMgr.ctxMgr() as ctxMgr:
        result = ctxMgr.someFunc()

    if result:
        return True, result
    return False, None

我正在处理的单元测试如下所示。

import mock
import unittest
import myModule as myModule

class MyUnitTests(unittest.TestCase):

    @mock.patch("myModuleWithCtxMgr.ctxMgr")
    def testMyFunc(self, mockFunc):
        mockReturn = mock.MagicMock()
        mockReturn.someFunc = mock.Mock(return_value="val")
        mockFunc.return_value = mockReturn
        result = myModule.myFunc("arg")

        self.assertEqual(result, (True, "val"))

测试失败是因为 result[0] = magicMock() 而不是我配置的返回值(我想)。

我尝试了几种不同的测试变体,但我似乎无法模拟 ctxMgr.someFunc() 的返回值。有谁知道我如何做到这一点?

谢谢!

【问题讨论】:

    标签: python-2.7 mocking python-mock


    【解决方案1】:

    错误提示:

    First differing element 1:
    <MagicMock name='ctxMgr().__enter__().someFunc()' id='139943278730000'>
    'val'
    
    - (True, <MagicMock name='ctxMgr().__enter__().someFunc()' id='139943278730000'>)
    + (True, 'val')
    

    错误包含模拟名称,它准确地向您显示需要模拟的内容。注意__enter__对应Context Manager protocol

    这对我有用:

    class MyUnitTests(unittest.TestCase):
    
        @mock.patch("myModuleWithCtxMgr.ctxMgr")
        def testMyFunc(self, mockCtxMgr):
            mockCtxMgr().__enter__().someFunc.return_value = "val"
            result = myModule.myFunc("arg")
    
            self.assertEqual(result, (True, "val"))
    

    请注意,它们中的每一个都是一个单独的 MagicMock 实例,您可以对其进行配置:

    • mockCtxMgr
    • mockCtxMgr()
    • mockCtxMgr().__enter__
    • mockCtxMgr().__enter__()
    • mockCtxMgr().__enter__().someFunc

    MagicMocks 是惰性创建的,但具有标识,因此您可以通过这种方式配置它们,它就可以正常工作。

    【讨论】:

      猜你喜欢
      • 2019-01-22
      • 1970-01-01
      • 2022-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-07
      • 2015-10-17
      相关资源
      最近更新 更多