如何Mock带参数的commutils.UserNameMapper类?解决self参数报错
问题:Mock类实例方法时出现“self param expected”错误
场景代码
待测试的refactorReport方法:
def refactorReport(df): """Enhance with additional information as needed""" for userclass in ['ClassA', 'ClassB', 'ClassC']: df['%s_Region'%userclass] = df[userclass].apply(lambda x: commutils.UserNameMapper(x).Region()) return df
测试用的DummyUserNameMapper类及测试代码:
class DummyUserNameMapper(): def __init__(self, thename): self.thename = thename def Region(self): print(self.thename) return 'Region%s'%self.thename[-1] class ModuleTests(unittest.TestCase): def setUp(self): data = [ ('Name 1', 'Apple', 'Mango', 'Orange'), ('Name 2', 'Pear', 'Apple', 'Banana'), ('Name 3', 'Banana', 'Mango', 'Orange'), ('Name 4', 'Apple', 'Pear', 'Orange'), ('Name 5', 'Pear', 'Mango', 'Orange'), ] self.records = pd.DataFrame(data, columns=['Name', 'ClassA', 'ClassB', 'ClassC']) def test_refactorReport(self): with mock.patch("commutils.UserNameMapper", return_value=DummyUserNameMapper): print(refactorReport(self.records)) @mock.patch('commutils.UserNameMapper') def test_refactorReport_New(self, mockUser): mockUser.return_value = DummyUserNameMapper print(refactorReport(self.records))
运行测试时出现“self param expected”错误。
错误原因
你错误地将DummyUserNameMapper类本身赋值给了Mock的return_value。当代码调用commutils.UserNameMapper(x)时,返回的不是类的实例,而是类本身。后续调用.Region()时,Python会把类作为第一个参数传入,但Region方法期望接收的是类的实例(即self参数),因此触发错误。
正确解决方案
方案1:使用side_effect替代return_value
side_effect可以接收一个类,每次调用Mock类时,会自动传入参数创建实例:
class ModuleTests(unittest.TestCase): def setUp(self): data = [ ('Name 1', 'Apple', 'Mango', 'Orange'), ('Name 2', 'Pear', 'Apple', 'Banana'), ('Name 3', 'Banana', 'Mango', 'Orange'), ('Name 4', 'Apple', 'Pear', 'Orange'), ('Name 5', 'Pear', 'Mango', 'Orange'), ] self.records = pd.DataFrame(data, columns=['Name', 'ClassA', 'ClassB', 'ClassC']) def test_refactorReport(self): with mock.patch("commutils.UserNameMapper", side_effect=DummyUserNameMapper): result_df = refactorReport(self.records) print(result_df) # 可添加断言验证结果,例如: # self.assertEqual(result_df['ClassA_Region'].iloc[0], 'Regione') @mock.patch('commutils.UserNameMapper') def test_refactorReport_New(self, mockUser): mockUser.side_effect = DummyUserNameMapper result_df = refactorReport(self.records) print(result_df)
方案2:直接Mock实例的Region方法(更简洁)
无需编写完整的Dummy类,直接MockUserNameMapper实例的Region方法返回值:
class ModuleTests(unittest.TestCase): def setUp(self): data = [ ('Name 1', 'Apple', 'Mango', 'Orange'), ('Name 2', 'Pear', 'Apple', 'Banana'), ('Name 3', 'Banana', 'Mango', 'Orange'), ('Name 4', 'Apple', 'Pear', 'Orange'), ('Name 5', 'Pear', 'Mango', 'Orange'), ] self.records = pd.DataFrame(data, columns=['Name', 'ClassA', 'ClassB', 'ClassC']) @mock.patch('commutils.UserNameMapper') def test_refactorReport_simple(self, mockUser): # 获取Mock类的实例对象 mock_instance = mockUser.return_value # 静态返回固定值 # mock_instance.Region.return_value = 'RegionX' # 或者根据输入动态返回结果 def dynamic_region(): # 获取创建实例时传入的参数x x = mockUser.call_args[0][0] return 'Region%s' % x[-1] mock_instance.Region.side_effect = dynamic_region result_df = refactorReport(self.records) print(result_df)
内容的提问来源于stack exchange,提问作者Pankaj Singh
相关产品推荐
相关产品推荐

