在Python中模拟实例化对象与类



有人能帮我理解unitest.patch实例化对象和类之间的区别吗?我正在尝试模拟对sagemaker.Session.describe_training_job的调用。我有一个函数,它调用my_session = sagemaker.Session(),然后稍后调用my_session.describe_training_job()

#my_module.py
import sagemaker

def do_something_with_session(local_session, job):
return local_session.describe_training_job(job)
def my_function(args):
my_session = sagemaker.Session()
description = do_something_with_session(my_session, args.job)

如果我使用下面的测试,my_session对象是预期的MagicMock,但没有describe_training_job方法:

@patch("sagemaker.Session")
def test_class(self, sagemaker_session):
sagemaker_session.describe_training_job = MagicMock(return_value=self.mock_return_value)
my_module.my_function(args=self.mock_args)

如果我改为这样做:

@patch("sagemaker.Session")
def test_class(self, sagemaker_session):
# Need to instantiate an object for this to work
session_object = sagemaker_session()
session_object.describe_training_job = MagicMock(return_value=self.mock_return_value)
my_module.my_function(self.mock_args)

然后测试按预期进行:my_session对象是一个带有describe_training_job方法的MagicMock,该方法总是返回我设置的值。

有人能帮助理解这里的行为吗?我注意到,当我尝试使用类时,MagicMock的name参数是Session,但当我实例化对象时,它是Session()。不确定这对绑定有何影响。

mock是一个占位符对象,它没有mock方法(尽管它可能知道如果使用autospec可以调用哪些方法(。您没有显式提供的对mock的每个方法调用都只返回另一个mock对象。

如果模拟一个类,并且该类在测试的代码中被实例化,那么得到的实例将是另一个模拟。实例化只是mock的__call__,它像每次调用一样返回另一个mock(并且它总是为同一个调用返回相同的mock(。与函数调用的结果类似,此mock可以通过return_value访问。

如果像第一个例子中那样在类mock上设置一个属性,那么它只绑定到该类mock,而不绑定到实例mock,因此这允许只模拟类方法。这里要理解的要点是,类mock和实例mock不像它们所嘲笑的类和实例那样相关。两者都有相同的Mock类型,并且实例mock不知道创建它的类mock

这意味着必须始终在实例mock上设置实例方法属性,正如您在第二个示例中所做的那样。使用return_value相当于此,因此您也可以编写:

sagemaker_session.return_value.describe_training_job = MagicMock(return_value=self.mock_return_value)

最新更新