If you have Spring controller that uses repository objects, it can become a bit messy to write tests with mocks that have to mock various repository object methods like save() etc. Instead, you can use
Here is an example controller that uses repository objects:
@RestController public class StateManagerController { public StateManagerController(XRepository aRepository, YRespository yRepo) {
}
public void aMethod() {
// use xRepo, yRepo : e.g., xRepo.save() , yRepo.delete() etc.
}
...
}
To test methods of this controller that use the repository objects, you will likely have to mock each repository collaborator object. Then you can get into lots of mocking details that make your tests ugly.
Instead, I find that using the following pattern greatly simplifies both your code and tests. It's very simple but works great.
1. In your controller, only inject/depend on @Service objects. Don't use repository objects directly
2. Test your controllers using mocks of these service objects
3. Test your Service objects separately using mocks of the repository objects
For example, the above could be rewritten as:
StateManagerController.java:
@RestController public class StateManagerController { private final AService aService; public StateManagerController(AService alertService) { this.alertService = alertService; }
public void aMethod() {
// use aService instead of repo
}
...
}
AService.java:
@Service public class AService { private final XRepo xRepo; public AService(XRepo xRepo) { this.xRepo = xRepo; }
public void aMethod() {
// use xRepo
}
...
}
Now, your tests for StateManagerController become a lot simpler since you just have to mock AService and not worry about repository methods liek save etc
AService alertService = mock(AService.class); when(alertService.updateAlertStatus(1L).thenReturn(1); StateManagerController controller = new StateManagerController(aService); // exercise ResponseEntity<?> alertResponse = controller.updateAlert(1L); // ensure reponse is correct assertThat(alertResponse).isEqualTo(ResponseEntity.ok().build());
Not only is your testing cleaner, your code organization is also cleaner and you get a lot of reuse from the Service classes that you can use in other controller or non controller objects as well.
Enjoy!
Comments
Post a Comment