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
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
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