Doesn’t this “contaminate” the entire calling function though, as in you now have to specify it is impure?
There are other approaches you can take too, like encoding your effects in a monad which has a different runtime representation in tests. It's like mocking on steroids with type safety.
This doesn't negate the advantages of tracking effectful code in the type system, and there's still plenty of code that can be pure.