Django rest framework: testing update action doesn't return 400 if request data is invalid
<p>I'm writing unit tests for a particular viewset, and am finding that the response isn't as expected. The <a href="http://www.django-rest-framework.org/api-guide/generic-views/#updatemodelmixin" rel="nofollow">docs</a> suggest that incorrect data will result in status code 400, but I get 200...</p>

<pre><code> def test_retrieve_resource_patch_authenticated(self):
    """Update field, then try and patch a protected field (username)"""
    self._require_login()

    # Attempt to patch protected field, and non-existant field
    test_response_2 = self.client.patch(self.url_detail, data={'username': 'cantchangethis'}, format='json')
    test_response_3 = self.client.patch(self.url_detail, data={'usernamedoesntexist': 'new_username'}, format='json')
</code></pre>

<p>Both test_response_2.data and test_response_3.data contain the original resource (so correctly, no updates have been applied) but with status_code 200 and no message. I've tried adding read_only to the serializer (in several places) and writing a validate method, which gets called in production, but doesn't seem to do anything in testing. What am I doing wrong?</p>

<p>views.py</p>

<pre><code>class UserProfileView(generics.RetrieveUpdateDestroyAPIView):

  serializer_class = user.serializer.UserProfileSerializer
  permission_classes = [permissions.IsAuthenticated]
  lookup_field = 'username'

  def get_queryset(self):
      user = self.request.user
      return User.objects.filter(username=user)
</code></pre>

<p>serializer.py</p>

<pre><code>class UserProfileSerializer(serializers.HyperlinkedModelSerializer):
  username = serializers.CharField(read_only=True)
  query = serializers.HyperlinkedRelatedField(many=True, view_name='query-detail', read_only=True)

  class Meta:
      model = User
      fields = ('username', 'first_name', 'last_name', 'email', 'query')
      extra_kwargs = {
          "username": {
              "read_only": True,
          },
      }

  def validate(self, data):
      if 'username' in data:
          raise Conflict('Usernames cannot be changed')
      return data
</code></pre>