Well, what I see right away is a type mismatch in your assertion.
assertEqual is String -> a -> a -> Assertion. You pass a String as the second argument, meaning a String should also be the third argument. However, your do expression is not returning String, but rather IO String.
Edit: To expand, once you mess with IO, you can't ever ditch it. You correctly extract the value out of IO with your <-, but then immediately wrap it back into IO with return. If you want to use the string, you must do it inside IO, something like:
do
contents <- hGetContents handle
assertEqual "They're equal" "Expected string" contents
Note that then your do would be returning IO Assertion. If you want to use the assertion value, you'd need to unwrap it similarly, and so on. Haskell doesn't let you get away with (hidden) side effects!