我有以下(简化)代码:
def get_redis()
return redis_instance
def bar(key, value, redis=get_redis())
redis.set(key, value)
def foo()
bar("key", value)在我的测试中,我希望模拟函数get_redis来返回fakeredis.FakeStrictRedis()的一个实例,所以我执行了以下操作
def test_foo(mocker):
mocker.patch("app.main.get_redis", return_value=fakeredis.FakeStrictRedis())
foo()模拟的函数没有效果,foo函数试图使用main中的get_redis函数连接到真正的redis。
如果我这样写的话
def bar(key, value)
redis=get_redis()
redis.set(key, value)这是可行的,但我可以将redis作为默认值传递。我怎么能嘲笑?
发布于 2020-10-12 04:31:38
我只需按以下方式稍微修改bar函数,以便在应用模拟之前不会调用您的函数:
def bar(key, value, redis=get_redis)
if callable(redis):
redis = redis()
redis.set(key, value)用这种方式编写函数意味着在调用函数时将应用模拟,而不是在应用任何模拟之前在启动时应用。简而言之,以这种方式编写bar,可以确保每次调用get_redis函数时,它都会通过您的bar函数进行传播。
发布于 2020-10-16 20:51:08
模拟没有什么问题,但您似乎误解了默认参数值是如何工作的。正如在Python语言引用中解释的那样,默认值是在函数 definition 执行时计算的。
在您的示例中,这意味着在定义get_redis时已经调用了原始bar:
def bar(key, value, redis=get_redis()):这个语句是在pytest导入模块时执行的,即在执行test_foo之前,所以在测试中模拟get_redis没有效果,因为到那时已经太晚了。
若要使默认的供应工厂函数可模拟,请使用None作为默认值,并使函数调用工厂,除非在调用中指定了另一个值:
def bar(key, value, redis=None)
redis = redis or get_redis()
redis.set(key, value)https://stackoverflow.com/questions/64285172
复制相似问题