使用pytest测试Django API时,ORM查询Sensor不存在的问题排查
问题分析与解决方案
核心问题:数据库环境不匹配
你的测试代码存在一个关键逻辑错误:
- 用
requests.post调用的localhost:8000是开发环境的Django服务,它操作的是本地开发数据库(即你settings配置的数据库)。 - 而
@pytest.mark.django_db让测试代码中的Sensor.objects.get()查询的是pytest自动创建的临时测试数据库,这两个数据库完全独立。
所以即便POST请求成功写入了开发数据库,测试代码在测试数据库里也找不到对应的Sensor记录。
验证与修复步骤
1. 先确认API请求是否真的成功
在测试中先检查响应状态码,排除请求本身失败的可能:
response = requests.post(f'{BASE_URL}{POST_URL}', json=body) assert response.status_code == 201 # 替换为你的API定义的成功状态码,比如200
另外,datetime.now()直接转字符串的格式可能不符合API要求,建议换成ISO标准格式:
"timestamp": datetime.now().isoformat(),
2. 方案一:使用Django测试客户端替代requests
这是Django测试的标准做法,直接在测试中调用视图,操作测试数据库,无需启动外部服务:
import pytest from datetime import datetime from django.test import Client from json_import.models import Sensor @pytest.mark.django_db class TestAPI: def test_smoke(self): client = Client() body = { "timestamp": datetime.now().isoformat(), "sensor_values": [ { "sensor_id": "sensor1", "value": "1.1" } ] } response = client.post('/api/write_values', json=body) assert response.status_code == 201 # 确认请求成功 # 此时查询的是测试数据库,和请求操作的是同一个库 sensor1 = Sensor.objects.get(sensor_id='sensor1') sensor_value1 = sensor1.sensor_values.last() assert sensor_value1.sensor_value == 1.1
3. 方案二:使用pytest的live_server fixture(启动测试服务器)
如果一定要用requests测试,可以用live_server fixture,它会启动一个连接测试数据库的临时服务器,确保请求和查询的是同一个数据库:
import requests from datetime import datetime from json_import.models import Sensor import pytest @pytest.mark.django_db class TestAPI: def test_smoke(self, live_server): POST_URL = "/api/write_values" body = { "timestamp": datetime.now().isoformat(), "sensor_values": [ { "sensor_id": "sensor1", "value": "1.1" } ] } response = requests.post(f'{live_server.url}{POST_URL}', json=body) assert response.status_code == 201 sensor1 = Sensor.objects.get(sensor_id='sensor1') sensor_value1 = sensor1.sensor_values.last() assert sensor_value1.sensor_value == 1.1
注意:使用live_server需要确保pytest-django已正确安装,且pytest.ini配置无误。
内容的提问来源于stack exchange,提问作者Motixa
相关产品推荐
相关产品推荐

