You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何pytest有时会判定两个字典不相等?

Why Your DRF Serializer Equality Assertions Fail Randomly

Ah, I see exactly what's going on here—this isn't a random bug at all, it's a quirk of how Django Rest Framework (DRF) handles serializer output. Let's break this down:

The Root Cause: DRF Doesn't Return Native Dictionaries

When you access serializer.data, you're not getting a standard Python dict or list—you're getting DRF's custom ReturnDict (for single objects) or ReturnList (for collections). These classes inherit from native dict/list but add an extra serializer attribute that references the serializer instance that generated them.

Why Equality Assertions Fail (But Your Validation Passes)

Your validation code works because it's almost certainly checking individual key-value pairs (e.g., assert d1['id'] == d2['id']), which ignores the container type and only cares about the actual data. Direct equality checks (assert d1 == d2) can fail in edge cases:

  • Nested structure type mismatches: If your serializer has nested serializers, the nested data will also be ReturnDict/ReturnList instances. While single-level comparisons between ReturnDict and dict work fine, some assertion tools (or custom recursive checks) might validate type consistency alongside content, causing failures.
  • Python version ordering differences: In Python 3.6 and earlier, native dicts are unordered, but DRF's ReturnDict inherits from collections.OrderedDict to preserve field order. If your expected d2 is a native dict with keys in a different order, the equality check will fail—this can seem "random" if you test across environments with different Python versions.

Fixes to Resolve the Issue

Here are three reliable ways to fix this problem:

1. Convert DRF Output to Native Types

Explicitly cast the serializer's output to a native dict or list before asserting equality. Since ReturnDict/ReturnList inherit from native types, this is straightforward:

serialized_data = dict(serializer.data)
assert serialized_data == expected_native_dict

For nested structures, this conversion will recursively turn all ReturnList instances into native lists too.

2. Use DRF-Friendly Assertion Methods

Django's test framework includes assertDictEqual and assertListEqual, which are designed to handle DRF's custom container types by comparing content rather than strict type matching:

from django.test import TestCase

class MySerializerTestCase(TestCase):
    def test_serializer_output_matches_expected(self):
        # ... set up your serializer and expected data ...
        self.assertDictEqual(serializer.data, expected_dict)

3. Accept DRF's Types as Valid

Since ReturnDict is a subclass of dict, you can adjust your assertions to account for this if you don't need strict native type checks:

from rest_framework.utils.serializer_helpers import ReturnDict

assert isinstance(serializer.data, (dict, ReturnDict))
assert serializer.data == expected_dict

This ensures you're checking for compatible types while still validating content equality.

内容的提问来源于stack exchange,提问作者Chathan Driehuys

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:23:17