4 ms·
There's a problem you're not seeing here. This solves it partially but in the end doesn't fix anything. The key thing here is redis is IO and it can't be tested
by formulathree 3y ago
There's a problem you're not seeing here. This solves it partially but in the end doesn't fix anything. The key thing here is redis is IO and it can't be tested.
Think of IO as a virus it pollutes the outer scope of anything it lies within. Anything that contains IO becomes IO and therefore is not unit testable. In fact any function marked with "await" or "async" is usually a good indicator of this pollution. Async await keywords actually spread around according to this exact logic I specified.
Example:
async def handler(request) -> response:
x = await iocall()
y = add(2, x)
return response(y)
iocall is in the scope of handler, handler becomes polluted with async and thus "not unit testable". I took the time to encapsulate pure addition logic into the add function, this makes add testable because it doesn't enclose over any IO functions.
That's the pattern of making unit testable code. You should try to move as much logic as possible into pure functions like add. Keep IO functions small and general and devoid of custom logic while segregating all your custom code into pure functions. Then just test these pure functions and leave everything else alone because all that other stuff goes into the realm of IO and integration tests.
You could get around this with mocking and using dependency injection but that comes with it's own set of problems including more complexity and spending the extra time to get the mocks to return results you want for each test. I would move these into the realm of integration tests rather then mock. In this case the usage of the flask test_client would still have to involve spinning up some sort of infra involving the database.
Your point about the unit test client from flask is completely valid for certain cases. It only works if the handler does not touch IO. In that case you wouldn't even need to mark the handler with the async keyword as nothing is awaited.