Skip to content
This repository has been archived by the owner on Mar 18, 2021. It is now read-only.

Best practices for POST and related tests #108

Closed
kbirch opened this issue Nov 2, 2016 · 3 comments
Closed

Best practices for POST and related tests #108

kbirch opened this issue Nov 2, 2016 · 3 comments

Comments

@kbirch
Copy link

kbirch commented Nov 2, 2016

Greetings:

A bit of a 2 part issue / question around the same topic...

1 - I may have missed documentation examples somewhere about this, but what I put together seems to be working. For a POST endpoint I'm just doing this inside my Controller class to get at the data I'm receiving:

await request.decodeBody();
Map body = request.requestBodyObject;

First question is, all good here?

2 - The main reason I'm asking is because I get major failure when I run this through a test case, unless I comment out the first line completely (decodeBody()). Here's the error:

Expected: 
	Status Code: 200
	Body: 'OK'
  Actual: TestResponse:<
	Status Code: 500
	Headers: x-frame-options: SAMEORIGIN
			 content-type: application/json; charset=utf-8
			 x-xss-protection: 1; mode=block
			 x-content-type-options: nosniff
			 server: aqueduct/1
			 content-length: 0
	Body: null>
   Which: Status Code 200 != 500

package:test                                       expect
test/facebook_controller_test.dart 38:7            main.<async>.<fn>.<fn>.<async>
dart:async                                         _SyncCompleter.complete
package:aqueduct/utilities/test_client.dart 279:5  TestRequest._executeRequest.<async>
dart:async                                         _SyncCompleter.complete
package:aqueduct/utilities/test_client.dart 354:3  TestResponse._decodeBody.<async>
===== asynchronous gap ===========================
dart:async                                         _Completer.completeError
test/facebook_controller_test.dart 39:6            main.<async>.<fn>.<fn>.<async>
dart:async                                         _SyncCompleter.complete
package:aqueduct/utilities/test_client.dart 279:5  TestRequest._executeRequest.<async>
dart:async                                         _SyncCompleter.complete
package:aqueduct/utilities/test_client.dart 354:3  TestResponse._decodeBody.<async>

The code comments in request.dart indicate the need to call decodeBody() first and it does work just fine on a deployed server, but the test fail is a bit of a nuisance requiring manual edits before running the test. Is this a bug or am I doing something wrong?

Also, I can't get any custom logging to work at all in my controller classes when running through a test case - everything from trying to log to a remote system like Rollbar through to just a standard print statement. That also works fine when deployed but just not when running a test. Any recommendations on how to approach that? The issue above was pretty tough to diagnose without having any logging capabilities in my Controller code during a test run.

Thanks in advance!

@joeconwaystk
Copy link
Member

  1. Are you using HTTPController? HTTPController decodes the body as part of its processing, so by the time you get your responder method invoked, requestBodyObject is already valid.
  2. Are you testing in IntelliJ IDEA? It sometimes doesn't pick up standard output, which is really a pain. Running tests from the terminal (pub run test -j 1) is what I do when it fails to pick up stdout. It's really obnoxious when you want to see the stack trace of the server itself, which is often. There is a flag on RequestController for this purpose, includeErrorDetailsInServerErrorResponses, which if true, returns the stack trace of a 500 in the JSON body.

@kbirch
Copy link
Author

kbirch commented Nov 2, 2016

Okay awesome, thank you. Re: item 1... Yes to HTTPController, and originally I had included the decode call as per the code comment and in the absence of other examples I could find:

 /// The request body object, as determined by how it was decoded.
 ///
 /// This value will be null until [decodeBody] is executed or if there is no request body.

But I see now that it is already called inside of your HTTPController code, cool - simplifies things nicely.

On item 2, command line does what I need, thank you. I had seen this issue in browser-based projects before but not backend projects to this point, probably should have played around a bit more before flagging it - thanks for bearing with me. And the flag on RequestController is super helpful - just tried it, works well.

All done here :) Thanks again.

@joeconwaystk
Copy link
Member

Btw, another reason HTTPController decodes the body for you (if and only if it plans to process the request) is because x-www-form-urlencoded data gets treated as query values for @HTTPQuery parameters, and so the body needs to be parsed prior to executing the responder method.

I also realized you just brought up an important point: we really need a forum for Aqueduct. We'll get working on that. Closing this issue.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants