mock/patch os.path.exists with multiple return values

廉价感情. 提交于 2019-12-23 10:41:09

问题


I'm trying to test a function that I made that iterates through a list, and calls os.path.exists for each item in the list. My test is passing the function a list of 2 objects. I need os.path.exists to return True for one of them and False for the other. I have tried this:

import mock
import os
import unittest

class TestClass(unittest.TestCase):
    values = {1 : True, 2 : False}
    def side_effect(arg):
        return values[arg]

    def testFunction(self):
        with mock.patch('os.path.exists') as m:
            m.return_value = side_effect # 1
            m.side_effect = side_effect # 2

            arglist = [1, 2]
            ret = test(argList)

Using either but not both of line #1 and #2 give NameError: global name 'side_effect' is not defined

I found this question and modified my code like so:

import mock
import os

class TestClass(unittest.TestCase):
    values = {1 : True, 2 : False}
    def side_effect(arg):
        return values[arg]

    def testFunction(self):
        mockobj = mock(spec=os.path.exists)
        mockobj.side_effect = side_effect

        arglist = [1, 2]
        ret = test(argList)

And this produces TypeError: 'module' object is not callable. I also tried switching these lines:

mockobj = mock(spec=os.path.exists)
mockobj.side_effect = side_effect

for this

mockobj = mock(spec=os.path)
mockobj.exists.side_effect = side_effect

and this

mockobj = mock(spec=os)
mockobj.path.exists.side_effect = side_effect

with the same error being produced. Can anyone point out what it is that I am doing wrong and what I can do to get this to work?

EDIT: After posting my answer below I realised that my first bit of code actually works as well, I just needed m.side_effect = TestClass.side_effect instead of m.side_effect = side_effect.


回答1:


So after a bit more research and trial and error, with most of the examples here: http://www.voidspace.org.uk/python/mock/patch.html, I solved my problem.

import mock
import os

def side_effect(arg):
    if arg == 1:
        return True
    else:
        return False

class TestClass(unittest.TestCase):
    patcher = mock.patch('os.path.exists')
    mock_thing = patcher.start()
    mock_thing.side_effect = side_effect
    arg_list = [1, 2]
    ret = test(arg_list)
    self.assertItemsEqual([1], ret)

test calls os.path.exist for each item in arg_list, and returns a list of all items that os.path.exist returned True for. This test now passes how I want it.




回答2:


you could have done self.side_effect I believe. since the initial definition was not global, calling side_effect looks inside the global scope



来源:https://stackoverflow.com/questions/21927057/mock-patch-os-path-exists-with-multiple-return-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!