如何Mock类的属性(另一个类的实例)以调用其方法?
问题与解决方案
问题描述
在测试Bar类的bar方法时,尝试Mock其foo属性(类型为Foo类实例),但用字符串"MockedFoo"作为Foo的Mock返回值,导致调用test_obj.bar()时抛出AttributeError: 'str' object has no attribute 'search'。需要修改Mock方式,让Bar的foo对象能调用Foo的search方法,且该方法返回指定列表。
原代码:
import unittest from mock import patch class Foo(object): def __init__(self): self.foo = 'foo' def search(self): # do something class Bar(object): def __init__(self): self.id = "123" self.name = "abc" self.foo = Foo() def bar(self): return self.foo.search() def test_bar(): # initialization of Bar object with mock.patch('lib.lib_foo.Foo', return_value="MockedFoo"): test_obj = Bar() test_obj.bar()
解决方案
你需要Mock一个包含search方法的对象,而不是字符串。有两种常用方法:
方法1:Mock Foo类,让其返回带search方法的Mock实例
修改patch的return_value为Mock对象,并给这个Mock的search方法设置返回值:
import unittest from mock import patch, Mock # 导入Mock class Foo(object): def __init__(self): self.foo = 'foo' def search(self): # do something class Bar(object): def __init__(self): self.id = "123" self.name = "abc" self.foo = Foo() def bar(self): return self.foo.search() def test_bar(): # 创建Mock对象,给search方法设置返回列表 mocked_foo = Mock() mocked_foo.search.return_value = ["item1", "item2"] # patch Foo类,让它返回这个Mock对象 with patch('lib.lib_foo.Foo', return_value=mocked_foo): test_obj = Bar() result = test_obj.bar() # 验证结果是否符合预期 assert result == ["item1", "item2"]
方法2:直接Mock Bar实例的foo属性(更精准)
如果不需要Mock整个Foo类,而是只针对当前test_obj的foo属性,可以直接patch实例的属性:
import unittest from mock import patch, Mock class Foo(object): def __init__(self): self.foo = 'foo' def search(self): # do something class Bar(object): def __init__(self): self.id = "123" self.name = "abc" self.foo = Foo() def bar(self): return self.foo.search() def test_bar(): test_obj = Bar() # 创建带search方法的Mock对象 mocked_foo = Mock() mocked_foo.search.return_value = ["test_result"] # 直接替换test_obj的foo属性 with patch.object(test_obj, 'foo', mocked_foo): result = test_obj.bar() assert result == ["test_result"]
两种方法都能解决问题,方法2更聚焦于当前实例的属性,避免影响其他地方的Foo类使用。
内容的提问来源于stack exchange,提问作者Muhammad Shaheer Munir
相关产品推荐
相关产品推荐

