How can I post data into test Client post request?

Question:

I’m writing a test to see if form data is validating on post request trying to create a Post object.

tests.py

def setUp(self):
    user = User.objects.create_user(email='[email protected]', password='test', name='test')
    self.user = User.objects.get(email='[email protected]')
    self.client.login(email=user.email, password=user.password)

@tag('fast')
def test_index(self):
    client = Client()
    response = client.post(reverse('index'), data={'user': self.user, 'body': 'Test'}, follow=True)
    print(response, self.user)
    self.assertTrue(Post.objects.filter(body='Test').exists())

but the test fails with message False is not true implying that the object with body "Test" was not created. I already tried encoding data with urlencode but it did not help.

Here is what print statement shows: <TemplateResponse status_code=200, "text/html; charset=utf-8"> test

views.py

def index(request):
    posts = Post.objects.all()
    if request.method == 'POST':
        form = NewPostForm(request.POST, request.FILES)
        if form.is_valid():
            new_post = form.save(commit=False)
            new_post.user = user
            new_post.save()
            return redirect('index')
    else:
        form = NewPostForm(instance=None)
    context = {
        'form': form,
        'posts': posts
    }

    return render(request, 'index.html', context=context)

Maybe the user isn’t being serialized correctly but when I remove it from data attribute (which would mean that the current user should be assigned to Post object) I get basically the same result.

Asked By: SLDem

||

Answers:

You could try adding Content-Type:application/json in the header of you request

as in the error message above it is showing the the request you are sending is in the plain text

Answered By: Saad Javaid Alvi

In the end I decided to just test it for valid response and leave the data validation part to the form validation test, here’s what it looks like now:

def test_index(self):
    client = Client()
    get_response = client.get('/home/', {}, True)
    post_response = client.post(reverse('index'), data={'body': 'Test'}, follow=True)
    self.assertEqual(get_response.status_code, 200)
    self.assertEqual(post_response.status_code, 200)

If anyone has any suggestions I would love to see them though because my particaular qestion problem still exists.

Answered By: SLDem

new_post.user = user should probably be new_post.user = request.user
Then you don’t even need to pass user in the POST and it’ll just auto grab it from the request
The 200 status isn’t very helpful in this situation because no matter what (create an object or fail to create one) it’ll redirect to index

So my guess would be the form is failing the validation.
There’s not enough info for me to give a direct Answer, but here’s some steps to debug:

  1. Place a print('Validation:', form.errors.as_data()) below+tabbed-left of the redirect('index')
    • This will let you know if the form is failing it’s validation
  2. Place a print('POST:', request.POST) below+tabbed-right of the request.method == 'POST':
    • This will let you see if the data is actually getting there in the first place
  3. Re-Run the Tests
    • Validation Error?:
      • maybe it’s missing a field.
      • maybe user is a required field and thus can’t pass validation without it.
        • Allow user to be blank and/or null + set User in the .is_valid() (like you’re doing)
    • Post Data Empty?: there’s a direction, why?

I just ran into a similar issue using Django 3.2.4, my data wasn’t getting there
I was using:

  • attempt 1: client.post('post/url', data=formdatadict, content_type='application/json')
  • attempt 2: client.post('post/url', data=json.dumps(formdatadict), content_type='application/json')
  • My Solution: client.post('post/url', data=formdatadict)
    Note: I’m using self.client.post() but c = Client() + c.post() would work

Sooo hopefully this helps someone with their debugging
(especially because tests take so long to run)

Answered By: Nealium
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.