typically, this means the singleton has outgrown its original intention, and should be made a standard object (read: not a singleton).
testability is one major reason. pains updating programs to use multiple instances are another. yet another: it's often a difficult bottleneck at execution. the singleton pattern is often overused, used for the wrong reasons, and leads to issues (like this).
so, you typically just make the object not function as a singleton anymore, or abstract its true shared exclusive data (if any) behind the interface of some class. this shared data and init/destroy sequence indicates that it is a singleton for the wrong reasons, or has grown to provide too much functionality.
as far as heavy objects: you can create initializers/constructors to support this use:
if you absolutely need (often for historic reasons, unless your team continues to write singletons) a big blob of global mutable state (which is the current sum of your program's singletons and other global state), i prefer to make one class to hold these -- then the holder is the only singleton and responsible for initialization/destruction. then the complexity of your global shared state becomes more obvious (coincidentally, the reason many people don't like doing this).
anyways, the singleton is tough to test and from what i have seen, most uses have been made singletons for no good reason -- this is just becomes a pain when you need to test, reuse, extend, et cetera.
then you can happily execute all your tests (in parallel) without elaborate start up/tear down sequences.