Slide 1

Slide 1 text

Spring Java Patterns A few things I’ve found useful when building web apps recently

Slide 2

Slide 2 text

Lends itself to good architecture ● MVC ● Service Layer ● DDD ● Various levels of public/private ● All your lovely patterns (AbstractUserDecoratorFactory) ;)

Slide 3

Slide 3 text

Service layer = Translation layer ● Into your domain terms ● Don’t leak implementation details (result object pattern)

Slide 4

Slide 4 text

Service With Result Object public class OrderService { public OrderCancellationResult cancelOrder(){ ... return new OrderCancellationResult(status, referenceNumber); } class OrderCancellationResult{ public OrderCancellationResult( String status, String ReferenceNumber){...}; public String getStatus(){...}; //Pending, Rejected, Awaiting Review public String getTransactionReferenceNumber(){...} } }

Slide 5

Slide 5 text

Doesn’t Leak HTTP status codes!

Slide 6

Slide 6 text

Testing Controllers in Spring + One mockMvc test to exercise annotations + Others directly call method - Error handling via controller advice

Slide 7

Slide 7 text

Controller Testing Testing through http avoids brittle tests, allows refactoring @Test public void getAccount() throws Exception { when(userService.findUser(anyInt())).thenReturn("element"); this.mockMvc.perform(get("/users/123") andExpect(status().isOk()); } @Test public void getAccount_Happy() throws Exception { when(userService.findUser(anyInt())) .thenReturn(new User("jim"); User result = controller.readUser(1238439) assertThat(result).Equals(new User("jim"))) } @Test(expected=RecordNotFound.class) public void getAccount_NotFound() throws Exception { when(userService.findUser(anyInt())).thenReturn(null); controller.readUser(1238439) } class GlobalControllerExceptionHandler { @ResponseStatus(HttpStatus.NOT_FOUND) @ExceptionHandler(RecordNotFound.class) public void handleNotFound() { return new ErrorResponse("Not Found"); } } @RestController class UserController{ @RequestMapping(value ="/users/{userId}", method = RequestMethod.GET) public Account getAccount(@PathVariable Long userId){} }

Slide 8

Slide 8 text

When to Mock (my opinion) Services! + DB interaction + Complex interaction + External Services

Slide 9

Slide 9 text

When not to mock... Arguable... + Small well-defined objects + individually unit tested. + No external dependencies + eg. Parsers, formatters, etc.

Slide 10

Slide 10 text

Use Judiciously ● Static Imports (especially with hamcrest/Mockito) ● Heavily configured MockMVC (eg mockFilterChain) ● Integration Tests Testing from inside a package (Legacy Code) **point of contention**