如何在该类实例方法的单元测试中模拟类实例

时间:2018-08-15 13:55:02

标签: python python-2.7

我正在尝试对some_function实例方法MyClass进行单元测试,该方法需要someapi.api实例。如何用一些返回值修补self.api.something1.something2(foo)

import someapi

class MyClass(object):

  def __init__(self,a,b):
    self.a = a
    self.b = b
    self.api = someapi.api(self.a, self.b)

  def some_function(self, foo):
    result = self.api.something1.something2(foo)

    new_result = dosomething(result)
    return new_result

所以我真正想要的是模拟此api的响应,以便我可以测试dosomething(result)是否满足我的要求。

@mock.patch('self.api.something1.something2', side_effect='something')
def testGet_circuits(self,pymock):
    result = some_function('foobar')
    expected_result= 'something'
    self.assertEqual(result, 'expected_result')

我尝试了

@mock.patch('someapi.api')
def testSome_function(self,someapi_mock):
    api = MyClass('a','b')
    result = api.some_function('foo')
    self.assertEqual(result,'newfoo')

我正在努力解决的是如何在some_function中模拟self.api.something1.something2(foo):(

2 个答案:

答案 0 :(得分:0)

您没有正确设置模拟。我使用您的代码编写了一个示例,并设法将一个有效的测试方法组合在一起。最终,这里发生的是您没有告诉模拟程序在代码运行时如何表现。您可能在正确的地方开始了模拟,但除此之外,模拟本身不再具有要允许代码运行而试图访问的任何属性。我将遍历代码来帮助说明:

class TestStuff(unittest.TestCase):

    @mock.patch('real_code.someapi.api', autospec=True)
    def testSome_function(self, someapi_mock):

        someapi_mock.return_value.something1 = mock.Mock(spec=Something)

        someapi_mock.return_value.something1.something2.return_value = 'newfoo'

        api = MyClass('a', 'b')
        result = api.some_function('foo')
        self.assertEqual(result, 'newfoo')

第一件事,请注意,我正在针对测试位置进行更多的嘲笑,这一点很重要,请牢记,您应该阅读here

对于模拟配置问题,我只能从您的真实代码中假设,api.something1.something2指示something1持有其他某个类的实例,该类使您可以访问something2方法。因此,在此假设下说明了示例。

现在,正如您在方法的第一行中看到的那样,我正在做的是告诉我的模拟确保它具有something1属性。重要的是要记住,在进行模拟时,甚至在设置spec and/or autospec时(如我在示例中所使用的),也无法访问在__init__中创建的属性。因此,根据我的示例,您需要在模拟中提供它们。

第二行现在进行下一步,以模拟您试图从中获取结果的something2方法行为。完成此操作后,在调用您的真实代码时,它应该经历您设置的预期行为并返回预期的newfoo值。

要获得进一步的帮助,以下是我用来帮助进行功能测试的确切代码:

real_code.py

import someapi


class MyClass(object):

  def __init__(self,a,b):
    self.a = a
    self.b = b
    self.api = someapi.api(self.a, self.b)

  def some_function(self, foo):
    result = self.api.something1.something2(foo)

    new_result = dosomething(result)
    return new_result


def dosomething(foo):
    return foo

someapi.py

class api:
    def __init__(self, a, b):
        self.a = a
        self.b = b
        self.something1 = Something()


class Something:

    def something2(self, some_arg):
        return some_arg

答案 1 :(得分:0)

感谢所有答案对我的帮助 我结束了下面的工作,像个魅力。整个模拟过程看起来像兔子洞,我需要更深入地理解。

@mock.patch('someapi.api')
def testSome_function(self,someapi_mock):
    someapi_mock = return_value.something1.something2.return_value = 'mocked_value'
    api = MyClass('a','b')
    result = api.some_function('foo')
    self.assertEqual(result,'newfoo')