I'm building a location based REST API using Spring Boot, and I have run into a bit of a testing philosophy question. I have an object called Location that, among other things, requires a Google Places id to function. I've exposed the CRUD of this resource at /locations which delegates its work to LocationService.createLocation.

This class throws exceptions if 1). the GooglePlacesId doesn't exist or 2). if it isn't valid (not recognized on google places) or 3). the placeId already exists on saved Location. The GooglePlacesService is a dependency of the LocationService and handles communication with Google's api. Spring Boot allows for testing of your REST API directly with a mock web server and container thru MockMvc. When testing the location API, I mock out the googleService to allow me to test 2, and 1 and 3 are straightforward to test with how I seed the database or craft the payload.

So here's where I'm at a crossroads. There's another object Post to which a Location has a one to many relationship. A location shouldn't exist if it has no posts. So, if I'm creating a post for a Location that doesn't exist, and I use the /locations endpoint to create the location, I'm unable to transactionally create the location with the post. This would result in complex client error handling and object cleanup or some sort of running task that cleans up locations that are created with subsequent failures of the post creation. Would you recommend using this approach instead of allowing nested object creation?

The alternative I've gone for is allowing a location to be created through the /posts endpoint. This endpoint delegates to LocationService.createLocation for the embedded Location creation before creating the Post. This provides the necessary transactionality and simplifies client code. Have a broken a separation of concerns here?

As I am testing this endpoint, criteria 1-3 still apply for the nested Locations creation. What is the better testing approach: mocking the LocationService here and simply making sure this endpoint properly handles all exceptions thrown or actually crafting the payloads the same as in the testing of the /locations endpoint and creating true integration tests? The second seems like more work and duplication of testing. At the same time, criteria 1-3 are also all criteria of this endpoint and by creating true tests for them, I'm ensuring that these requirements are codified into this test. I'm also not fixing my test to the specific implementation of the PostService that happens to use the LocationService right now.

It's definitely not black and white, but I'm sure there's some compelling arguments for one direction

  • But if you go through /posts instead of /locations, there's no reason to keep /locations as an entry point for creationg Locations, right? Why would there be duplication of testing then? – guillaume31 Mar 12 '18 at 12:07
  • @guillaume31 true, in this exact case i no longer duplicate. But I have encountered similar scenarios where I would want both endpoints and I'm generally unsure what the right choice here is (if there even is one). – sunrize920 Mar 12 '18 at 12:20
  • 1
    I suggest you strip your Q from all unnecessary details and boil it down to that simple question then... and maybe provide schemas/diagrams to make it even clearer. – guillaume31 Mar 12 '18 at 12:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.