我编写了以下单元测试,当我运行它时,它会成功:
api \ test \ test_views.py:
class ProductListViewTest(APITestCase):
def test_get_products(self):
mock_products = MockSet()
mock_products.add(MockModel(mock_name='e1', prod_id='1')
client = APIClient()
with patch('api.models.Product.objects', mock_products):
response = client.get(reverse('product-list'))
serialized = ProductSerializer([{'prod_id': '1'}], many=True)
self.assertEqual(response.data, serialized.data)
其余代码:
# api\views.py:
from api.models import Product
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
# api\urls.py:
...
path('product/', views.ProductListView.as_view(), name='product'),
...
但是,一旦我将第二个测试添加到使用APIClient的同一TestCase中,第一个测试就会失败(response.data包含一个空数组)!
def test_second_test(self):
client = APIClient()
response = client.get('/')
self.assertEqual(True, True)
如果我删除了client.get()
调用(甚至没有意义),则第一个测试再次通过!
编辑:我观察到的一件事是,在ProductViewSet
中,Product
仅当我分别运行test test_get_products时才是MockSet
。如果使用“全部运行”运行两个测试,则Product
的类型为api.models.Product
。好像没有进行修补:/
答案 0 :(得分:0)
这是测试DRF ModelViews时的常见问题。在get_queryset
上覆盖ProductViewSet
:
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
def get_queryset(self):
return self.queryset.all()
这种方式将在每个请求上评估响应。
来自django docs:
评估QuerySet时,通常会缓存其结果。如果 自QuerySet以来,数据库中的数据可能已更改。 评估后,您可以通过调用以下查询获取同一查询的更新结果 先前评估过的QuerySet上的all()。
您的第二个测试在测试运行中被首先调用,并将空响应存储在ProductViewSet.queryset
中。因为queryset
是一个类变量,所以它在测试调用之间仍然存在。另外,django不知道数据库(模拟的)状态已更改,因此使用了缓存的QuerySet
。