prerequisites: I’m using the latest version of the Play! framework, and the Java version (not Scala).
I need to publish a message to a message queue when a user is created, and I’d like to test that behaviour. My issue is making this easily testable.
The Controller approach
In other frameworks, what I would’ve done would be to use constructor injection in the controller and pass in a mocked queue in my tests; however, with Play! the controllers are static, that means I can’t do new MyController(mockedQueue) in my tests.
I could use Google Guice and put an @Inject annotation on a static field in my controller, but that doesn’t feel very nice to me, as it either means I have to make the field public to be replaced in the test, or I have to use a container in my tests. I’d much prefer to use constructor injection, but Play! doesn’t seem to facilitate that.
The Model approach
It’s often said your logic should be in your model, not your controller. That makes sense; however, we’re not in Ruby here and having your entities interact with external services (email, message queues etc…) is considerably less testable than in a dynamic environment where you could just replace your MessageQueue static calls with a mocked instance at will.
If I make my entity call off to the queue, how is that testable?
Of course, both these situations are unnecessary if I do end-to-end integration tests, but I’d rather not need a message queue or SMTP server spun up for my tests to run.
So my question is: How do I model my Play! controllers and/or models to facilitate testing interactions with external services?
As I see, there’s not a clean solution for this.
You could use an Abstract Factory for your dependencies. This factory could have setter methods for the objects it produces.
}
Your test would look like this:
If you don’t want to expose the setter methods of the factory, you could create an interface and configure the implementing class in your tests.
Another option would be the use o PowerMock for mocking static methods. I’ve used before and it works relatively fine for most cases. Just don’t overuse it, or you’re in maintenance hell…
And finally, since your willing to use Guice in your application, this could be a viable option.
Good luck!