在Python中使用mock模拟多个响应
我正在尝试为我用 mock 写的 Rest 客户端编写单元测试。
假设这个类叫做 Foo
,它有两个方法:get_foo()
和 get_bar()
。
这是我的测试类:
fake_foo_response= 'foo'
class FooTestCase(unittest.TestCase):
def setUp(self):
self.patcher = patch('foo', fake_foo_response)
self.patcher.start()
self.foo = Foo()
def tearDown(self):
self.patcher.stop()
def test_get_foo(self):
response = self.foo.get_foo()
self.assertEqual(response,'foo')
我基本上是参考了这个教程才做到的:http://seminar.io/2013/09/27/testing-your-rest-client-in-python/
但是现在,我也想测试一下 bar,应该怎么用这种方法来测试 bar 呢?谢谢!
1 个回答
0
你可能会发现使用 MagicMocks 比使用补丁更简单,下面这种方式应该会对你有帮助:
from mock import MagicMock
fake_foo_response = 'foo'
fake_bar_response = 'bar'
class FooTestCase(unittest.TestCase):
def setUp(self):
self.foo = Foo()
self.foo.get_foo = MagicMock(return_value=fake_foo_response)
self.foo.get_bar = MagicMock(return_value=fake_bar_response)
def test_get_foo(self):
response = self.foo.get_foo()
self.assertEqual(fake_foo_response, response)
def test_get_bar(self):
response = self.foo.get_bar()
self.assertEqual(fake_bar_response, response)
不过,我觉得你需要看看你在测试的到底是什么。在你的例子中,你实际上只是:
- 创建了一个
Foo
对象的实例。 - 把一个函数的返回值改成了特定的值。
- 调用了这个被改过的函数(也就是不是原来的函数),并检查返回值。
你实际上并没有在测试 get_foo
函数,因此你上面展示的测试并没有什么实际意义。不过,你这里展示的技术对于测试像 REST 客户端这样的东西非常有用(因为它需要调用测试单元外部的服务)。假设你真正的 get_foo
实现是这样的:
- 对输入参数进行一些处理
- 调用一个外部网址,并获取响应(这部分你想要模拟)
- 对响应进行一些处理,并可能返回一些东西给调用者
如果你要对这个函数进行单元测试,你应该写一个测试来测试 get_foo
,并检查上面第 1 和第 3 点的行为,但对第 2 点进行补丁。这种补丁方式非常有价值,因为你可以用它来测试 get_foo
,同时模拟掉单元外部的调用,例如:
class Foo:
def get_foo(self, input):
url_param = <do something with input>
response = self._call_url(url_param)
output = <do something with response>
return output
class FooTestCase(unittest.TestCase):
def setUp(self):
self.foo = Foo()
self.foo._call_url = MagicMock(return_value='some response')
def test_get_foo(self):
output = self.foo.get_foo('bar')
self.assertEqual('ni', output)
现在,你可以使用补丁(通过 MagicMock
)来测试你 get_foo
方法中的代码,而不需要依赖于调用单元外部的东西。
希望这对你有帮助。