在Python中模拟函数参数

3 投票
3 回答
6404 浏览
提问于 2025-04-19 22:47

假设我有一个这样的函数:

from datetime import date

def get_next_friday(base_date=date.today()):
   next_friday = ...
   return next_friday

然后我有一个celery任务,用来调用这个函数,但不传入base_date这个参数。

@celery_app.task
def refresh_settlement_date():
   Record.objects.update(process_date=get_next_friday())

在我的单元测试中,我正在运行refresh_settlement_date()这个任务,但在调用get_next_friday()时,它没有提供base_date。我的问题是,如何模拟这个参数,以便测试未来的日期呢?

我想避免把参数改成refresh_settlement_date(base_date),因为这样做没有实际意义,只是为了单元测试。

3 个回答

1

我刚试了一下,这个方法好像有效:

首先,我需要复制这个函数:

old_get_next_friday = get_next_friday

然后进行修补:

with patch.object(get_next_friday) as mocked_func:
    for i in range(8):
        mocked_func.return_value = old_get_next_friday(date.today() + timedelta(days=i))
        refresh_settlement_date()
4

另一种方法是修改当前日期。

这里有一个相关的讨论,里面有很多选项:


我最喜欢的选项是使用一个叫做 freezegun 的第三方模块。

你只需要添加一行代码,非常简单易读:

@freeze_time("2014-10-14")
def test_refresh_settlement_date_in_the_future(self):
    ...
1

你需要使用 @patch 来对 get_next_friday() 这个函数进行处理,并把它返回的值换成你想要的值:

date_in_the_future = date.today() + timedelta(50)
next_friday_in_the_future = get_next_friday(base_date=date_in_the_future)

with patch('module_under_test.get_next_friday') as mocked_function:
    mocked_function.return_value = next_friday_in_the_future
    
    # call refresh_settlement_date

撰写回答