Consider a simple web application, I'll use a Python(ish) example, but i think the question is relevant for other languages as well.
The user is trying to fetch a page, and in order to render that page, the application has to make an external call to a remote service. In the example, I'll try to separate concerns: collecting input parameters, and calling the actual remote service.
def view(request):
foo = float(request.POST['foo'])
return Response(process_foo(foo))
def process_foo(foo):
return remote_service.get('/bar', data={'foo': foo})
In the example, view is a function that's responsible for transforming the incoming request to a Response, and process_foo is responsible for performing some business logic.
What kind of unit tests make sense here?
A few preferences:
- In
view, I'd expectprocess_footo be a black-box, so I'd like to replace it with something during testing, so I can refactorprocess_foowithout breaking unit tests forview. - In
process_foo, I'd like to replace the callremote_service.get, as it's an expensive operation.
Considering the restrictions above, I'm not sure what kinds of unit tests make sense here. In view, I could make an assertion about that process_foo was called with foo, but when I make changes to process_foo, this test will not break. The same is true for testing process_foo: if I make an assertion on that remote_service.get was called with the right URL and the right parameters, that'll not break when the remote URL changes (or it no longer accepts the same parameters).
To me it feels like that somehow I should test that foo was extracted from request.POST, but it seems that there's no reasonable way to do this.
I'm aware that integration tests can solve this problem, I'm looking for a possible solution about how the problem above could be solved with unit tests (if there's a solution at all).