Python单元测试Mock补丁对象而不是方法

4

我在使用Python中的Mock进行单元测试时遇到了困难。我有一个类中的方法start_thing()需要进行测试:

class ComplexClass:
   def __init__(self, lots, of, args):
       self.lots = lots
       ..

   def start_thing(self):
        import pdb; pdb.set_trace()
        print "some error!!"
        assert False

这个类本身就比较复杂,手动模拟起来很麻烦。这就是为什么我开始尝试使用Mock。

我想设置一个模拟实例,以便轻松运行单元测试,但不模拟start_thing()方法,以便测试真正的start_thing()实现而不是模拟版本。因此我创建了这个:

class TestComplexClass(TestCase):
     @patch.object(module.ComplexClass, 'start_thing')
     def test_start_thing(self, mock_method):
        ComplexClass.start_thing()

当进行测试时,我的实际方法start_thing()中未命中调试跟踪、断言或打印语句,这表明我已经对类和方法进行了模拟 - 而我只想模拟对象并测试真正的方法。我在这里做错了什么?这是否可能?
我发现许多使用Mock的示例展示了如何创建要测试的方法的模拟版本,但我认为这有点毫无意义,因为我不想检查它是否被正确调用,而是想测试真实代码中的实现,并模拟它所属的类以便更容易创建。
也许我没有完全理解Mock测试的概念?
1个回答

3

我认为你不是想嘲笑那个类,而是将其存根,例如:

class ComplexClassStub(ComplexClass):
  def __init__(self):
    self.lots = None
    self.the_rest_of_the_args = None # Now your complex class isn't so complex.

class ComplexClassTest(unittest.TestCase):
  def Setup(self):
    self.helper = ComplexClassStub()

  def testStartThing(self):
    with mock.patch.object(self.helper, 'SomethingToMock') as something_mocked:
      expected = 'Fake value'
      actual = self.helper.start_thing()
      self.assertEqual(expected, actual)
      something_mocked.assert_called_once_with()

好的,我明白了。感谢你的帮助!这并不那么糟糕。这个存根通常是与测试一起创建的吗? 您能解释一下使用Mock等方式测试调用方式与测试实际方法体的价值吗? - Colin Riddell
如果你在模拟测试功能中重要的某些内容,那么使用assert_called_once_with和/或assert_has_calls可以强制执行你所模拟的内容被调用的方式与你期望的完全一致。 - Dan
非常感谢。这很有道理,非常有用。再次感谢! - Colin Riddell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接