--
You received this message because you are subscribed to the Google Groups "Play framework dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framework-...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
(Cc'ing play-framework - I hope you don't mind!)Brennan, I agree with your general approach, but I think you could do this without embedding a WikiPage into the Result object. Personally I think it's better to keep Result focused on low-level concerns like HTTP headers and bytes, and to keep your business logic in a higher layer.
What I'd suggest is that you break down your request processing logic a bit more so that you can separately unit test the different bits of internal logic within your controller.Suppose your controller method contained code like:val wikiPage: WikiPage = wikiPageLogic.getWikiPage(id)wikiPageEncoding.encodeWikiPage(wikiPage) <-- constructs a Result object or a string to go into a ResultYou can easily unit test your business logic, i.e. wikiPageLogic.getWikiPage. Your tests would be able to operate on nice objects without needing to worry about the messy details of string encoding.You can separately unit test your encoding logic, i.e. wikiPageEncoding.encodeWikiPage. Your encoding unit tests would deal with the messy business of making sure that objects are properly encoded into the correct strings.Finally, if you like, you can write integration tests to make sure the controller does the right thing when it combines the business and encoding logic together. You could test that, for a given fake request, you get the correct Result. Since the encoding logic has been separated out, you can use it to help generate assertions for the expected result:
assertEquals(wikiPageEncoding.encodeWikiPage(WikiPage(...)), res)CheersRichOn Fri, Apr 26, 2013 at 1:49 PM, Brennan Saeta <sa...@coursera.org> wrote:
Hey,Perhaps I wasn't clear. Below is what a test currently looks like:@Testdef pageNotVisibleAdmin() {when(wikiStore.getWikiBody(123, "page", None)).thenReturn(Some(sampleWikiPage().copy(visible = false), markdownBody))val res = controller.getWikiPage(123, "page", None)(RequestHelpers.fullFakeRequest(GET, "/123/page?fields=content", 123, "wiki_admin"))assertEquals(OK, status(res))assertTrue(contentAsString(res).contains("BODY")) // <--- This sucks!}sampleWikiPage() - Helper function that returns a case class - used for mocking out the database.We don't want to write crufty software with a manager, a controller, a data accesser, a factory, and a factory factory manager. That said, we cannot write "full-application" tests that boot up the whole Play stack. We want to just test our controllers in isolation, mocking out constructor-injected dependencies. Given the result from our controller, we would like to be able to test the response body. Although it's possible to take the contentAsString(res), parse that as Json, and then re-parse that back into our case class, it would be much easier if we could subclass result, and keep around the case class that generated the Json in the first place. (Also to be typesafe! Right now, the type that generated the response is lost, so although we write a bunch of typesafe code for the rest of the stack, we can't here.) This is similar to how we have the WrappedRequest available for subclassing requests (that is used quite effectively in SecureSocial, for example, to add user information, etc.) Does that make sense?Ideally, a test looks like:
@Testdef pageNotVisibleAdmin() {when(wikiStore.getWikiBody(123, "page", None)).thenReturn(Some(sampleWikiPage().copy(visible = false), markdownBody))val res = controller.getWikiPage(123, "page", None)(RequestHelpers.fullFakeRequest(GET, "/123/page?fields=content", 123, "wiki_admin"))assertEquals(OK, status(res))assertEquals(WikiPage(...), restObject(res)) // <-- This is what we're looking for. Ideally it can be type-checked if we were using specs2's `====`}Best,-BrennanOn Thu, Apr 25, 2013 at 6:15 PM, Rich Dougherty <ri...@rd.gen.nz> wrote:
OK, testing on ordinary classes sounds like a good idea. :)I think you can achieve what you want without any changes to Play. Actions basically do Request => Result, but you can decompose that into parts for easier testing.Request => MyRequestMyRequest => MyResult (business logic goes here)MyResult => ResultYou can even write your own kind of Action to hide the first and last parts of the pipeline.I did something sort of similar when I wrote a little Play app to handle Github push events.Would that work for you?CheersRich