2014-02-21 23 views
2

我试图测试一个函数,我通过列表进行迭代,并为列表中的每个项目调用os.path.exists。我的测试是将函数传递给2个对象的列表。我需要os.path.exists为其中一个返回True,为另一个返回False。我曾经尝试这样做:模拟/修补程序os.path.exists具有多个返回值

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) 

无论是使用而不是线的两个#1和#2给出NameError: global name 'side_effect' is not defined

我发现这个question和修改我的代码如下所示:

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) 

这产生TypeError: 'module' object is not callable。 我还试图切换这些行:

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

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

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

具有相同的错误被生产。任何人都可以指出我做错了什么,以及我能做些什么来实现这个目标?

编辑: 发布我的回答下面我意识到,我的代码第一位实际工作为好,我只是需要m.side_effect = TestClass.side_effect而不是m.side_effect = side_effect后。

回答

3

因此,经过多一点研究和试验和错误,这里的大多数例子:http://www.voidspace.org.uk/python/mock/patch.html,我解决了我的问题。

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电话os.path.existarg_list每个项目,并返回os.path.exist退换True所有项目的列表。现在这个测试通过了我想要的方式。

+0

如果函数在两个调用中具有相同的参数会怎样? – hithwen

+0

你是什么意思?如果'os.path.exists'传递给两个调用的1?然后它会返回True,因为这是副作用所说的。但是它不会被同一个参数传递两次,因为'test'函数遍历'arg_list'并为列表中的每个元素调用'os.path.exists'。所以只要列表中的两个元素都不是“1”,那么它将按预期工作。 –

+0

我的意思是,如果我想用相同的参数调用os.path.exists两次,并返回第一个False,然后返回True。我想出了如何定义一个函数来计算被调用了多少次并返回不同的值并将其用作side_effect。 – hithwen

0

你可以做到self.side_effect我相信。因为最初的定义不是全局的,所以在全局范围内调用side_effect看看

相关问题