At IMVU, we built up a bit of scaffolding along these lines: https://gist.github.com/andyfriesen/43d886ce60927c69b3d1
The basic premise is that all our business actions can either be run "for real" through Yesod, or within a State-based framework that's part of our standard testing scaffold.
The end result is that it's trivial to write tests that arrange for the database, clock, sockets, and so forth to be in precisely the state we want them to be for the test, and to sense everything afterward.
Running these tests as pure State actions has additional benefits:
Since State operates by making successive state copies for each "mutation", test fixtures are easily effected by performing some actions and saving the produced state. Individual tests can start from this state as many times as desired. The state is immutable, so test interference is impossible.
Additionally, tests run without access to IO. This means that the compiler rejects any test which could forseeably intermittently fail.