I have a Controller which uses an application service to accomplish its tasks. The service class is starting to grow big and developing multiple dependencies. So I am thinking of replacing the single big service class with multiple command handlers, each handling a single responsibility. This is how the old and the new code will look like (simplified):
Old Code
@Component
@Path("/app/jobs")
public class JobController {
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<JobDto> getJobs() throws JobException {
return jobService.getJobs();
}
@PUT
@Path("{job_id}/assigned_to/{user_id}")
public Response assignTo(
@PathParam("job_id") @NotNull String jobId,
@PathParam("user_id") @NotNull String userId
) throws JobException {
jobService.assignJobTo(jobId, userId);
return Response.status(Response.Status.CREATED).build();
}
...
}
New Code
@Path("/app/jobs")
public class JobController {
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<JobDto> getJobs() throws JobException {
return new GetJobListCommandHandler(
new GetJobListCommand()
).handle();
}
@PUT
@Path("{job_id}/assigned_to/{user_id}")
public Response assignTo(
@PathParam("job_id") @NotNull String jobId,
@PathParam("user_id") @NotNull String userId
) throws JobException {
new AssignJobCommandHandler(
new AssignJobCommand(jobId, userId)
).handle();
return Response.status(Response.Status.CREATED).build();
}
...
}
I am basically following this tutorial in using command handlers. This patterns isolates each responsibility into one class which is great. But now, since my controller methods create the command handler objects, the handlers have become difficult to mock in unit tests. How do I write unit tests for the controller? Earlier the controller class had just a mocked version of the service object. One option could be to break the controller to service one uri (GetJobsController
, AssignJobController
, etc). But I don't want to do that. I like seeing the hierarchy of resources together and the path annotations work well like this. Is this the right way of going about this? What are the best practices or this approach and how do I write my unit test?
My application is a Spring+Jersey application.