我正在使用 FastAPI 静态文件类从服务器下载文件。一切正常,我可以使用 URL 轻松下载文件。
现在,我需要编写一个用于文件下载的测试用例,并且我不想仅仅为了测试目的而上传文件。我想模拟文件存在,所以我可以确保响应状态为 200。
但是,即使我模拟文件存在,我总是收到 404。你能帮我解决这个问题吗?
以下是 StaticFiles 在我的测试环境中的配置方式:
app_v1.mount("/files", StaticFiles(directory="server/api/v1/files"), name="files")
这是我的模拟测试用例:
def test_file_download(files_client: TestClient):
mock_file_path = "server/api/v1/files/mocked_file.png"
with patch('os.path.exists', return_value=True) as mock_exists:
# Perform the GET request to download the file
response_d = files_client.get("/files/mocked_file.png") # Adjusted path
# Validate the response
assert response_d.status_code == 200
assert mock_exists.called_once_with(mock_file_path)
请注意,如果我删除模拟并将文件物理放置到文件夹“server/api/v1/files/mocked_file.png”中,响应状态为 200。
另外,如果我评论断言response_d.status_code == 200,则测试运行成功,这表明调用了mock_exists. Called_once_with(mock_file_path)。然而不知何故,Staticfiles 仍然响应 404。
首先,我相信
StaticFiles
应用程序实际上并不使用os.path.exists
来检查文件是否存在,因为它需要打开它才能提供下载服务。它可能试图直接打开它,这就是它认为它不存在的方式。
另一件事是,您也不应该假设它实际上使用
os
模块。首先,应该检查这一点,并且它也可以在新版本中更改。
您需要实际模拟
StaticFiles
调用自身的所有系统调用,这将非常复杂,而且这样做没有任何意义。更好的方法是为测试范围创建静态文件。
我会简单地创建一个包含一些内容的文件,并在测试结束后将其删除。有一个名为
tempfile
的标准 Python 模块,但该模块在 /tmp
中写入临时文件,因此您对文件的绝对路径的控制有限。对于这个简单的测试用例,我认为简单地创建和删除要测试的文件会更容易。
为了使其更安全(例如,如果测试因异常退出,它可能会跳过临时文件的清理),我会创建一个小型临时文件管理器。
import os
class MyTemporaryFile:
def __init__(self, path: str, content: bytes):
self.path = path
self.content = content
def __enter__(self):
self.file = open(self.path, 'wb')
self.file.write(self.content)
self.file.close()
return self.path
def __exit__(self):
os.unlink(self.path)
并在您的测试中使用它:
def test_foo():
with MyTemporaryFile('/path/to/file', b'some test content') as filename:
# test your code
这将自动创建包含您传递的内容的文件,并确保在
with
语句完成后删除该文件,即使内部存在错误。