diff --git a/hls-test-utils.cabal b/hls-test-utils.cabal
--- a/hls-test-utils.cabal
+++ b/hls-test-utils.cabal
@@ -1,6 +1,6 @@
 cabal-version: 2.4
 name:          hls-test-utils
-version:       2.11.0.0
+version:       2.12.0.0
 synopsis:      Utilities used in the tests of Haskell Language Server
 description:
   Please see the README on GitHub at <https://github.com/haskell/haskell-language-server#readme>
@@ -43,14 +43,14 @@
     , directory
     , extra
     , filepath
-    , ghcide                  == 2.11.0.0
-    , hls-plugin-api          == 2.11.0.0
+    , ghcide                  == 2.12.0.0
+    , hls-plugin-api          == 2.12.0.0
     , lens
     , lsp
     , lsp-test                ^>=0.17
     , lsp-types               ^>=2.3
-    , neat-interpolation
     , safe-exceptions
+    , string-interpolate
     , tasty
     , tasty-expected-failure
     , tasty-golden
diff --git a/src/Development/IDE/Test/Diagnostic.hs b/src/Development/IDE/Test/Diagnostic.hs
--- a/src/Development/IDE/Test/Diagnostic.hs
+++ b/src/Development/IDE/Test/Diagnostic.hs
@@ -69,7 +69,7 @@
       | ghcVersion >= GHC96 =
         case (mbExpectedCode, _code d) of
           (Nothing, _)                         -> True
-          (Just expectedCode, Nothing)         -> False
+          (Just _, Nothing)                    -> False
           (Just expectedCode, Just actualCode) -> InR expectedCode == actualCode
       | otherwise =  True
 
diff --git a/src/Test/Hls.hs b/src/Test/Hls.hs
--- a/src/Test/Hls.hs
+++ b/src/Test/Hls.hs
@@ -357,7 +357,7 @@
 -- For example:
 --
 -- @
---  parameterisedCursorTest "Cursor Test" [trimming|
+--  parameterisedCursorTest "Cursor Test" [__i|
 --       foo = 2
 --        ^
 --       bar = 3
@@ -380,7 +380,7 @@
 -- TODO: Many Haskell and Cabal source may contain '^' characters for good reasons.
 -- We likely need a way to change the character for certain test cases in the future.
 --
--- The quasi quoter 'trimming' is very helpful to define such tests, as it additionally
+-- The quasi quoter '__i' is very helpful to define such tests, as it additionally
 -- allows to interpolate haskell values and functions. We reexport this quasi quoter
 -- for easier usage.
 parameterisedCursorTest :: (Show a, Eq a) => String -> T.Text -> [a] -> (T.Text -> PosPrefixInfo -> IO a) -> TestTree
diff --git a/src/Test/Hls/FileSystem.hs b/src/Test/Hls/FileSystem.hs
--- a/src/Test/Hls/FileSystem.hs
+++ b/src/Test/Hls/FileSystem.hs
@@ -29,8 +29,12 @@
   , directProjectMulti
   , simpleCabalProject
   , simpleCabalProject'
+  , atomicFileWriteString
+  , atomicFileWriteStringUTF8
+  , atomicFileWriteText
   ) where
 
+import           Control.Exception           (onException)
 import           Data.Foldable               (traverse_)
 import qualified Data.Text                   as T
 import qualified Data.Text.IO                as T
@@ -38,6 +42,7 @@
 import           Language.LSP.Protocol.Types (toNormalizedFilePath)
 import           System.Directory
 import           System.FilePath             as FP
+import           System.IO.Extra             (newTempFileWithin, writeFileUTF8)
 import           System.Process.Extra        (readProcess)
 
 -- ----------------------------------------------------------------------------
@@ -244,3 +249,25 @@
 simpleCabalProject' fps =
   [ simpleCabalCradle
   ] <> fps
+
+
+atomicFileWrite :: FilePath -> (FilePath -> IO a) -> IO a
+atomicFileWrite targetPath write = do
+  let dir = takeDirectory targetPath
+  createDirectoryIfMissing True dir
+  (tempFilePath, cleanUp) <- newTempFileWithin dir
+  (write tempFilePath >>= \x -> renameFile tempFilePath targetPath >> pure x)
+    `onException` cleanUp
+
+
+atomicFileWriteString :: FilePath -> String -> IO ()
+atomicFileWriteString targetPath content =
+  atomicFileWrite targetPath (flip writeFile content)
+
+atomicFileWriteStringUTF8 :: FilePath -> String -> IO ()
+atomicFileWriteStringUTF8 targetPath content =
+  atomicFileWrite targetPath (flip writeFileUTF8 content)
+
+atomicFileWriteText :: FilePath -> T.Text -> IO ()
+atomicFileWriteText targetPath content =
+    atomicFileWrite targetPath (flip T.writeFile content)
diff --git a/src/Test/Hls/Util.hs b/src/Test/Hls/Util.hs
--- a/src/Test/Hls/Util.hs
+++ b/src/Test/Hls/Util.hs
@@ -47,7 +47,7 @@
     -- * Extract positions from input file.
     , extractCursorPositions
     , mkParameterisedLabel
-    , trimming
+    , __i
   )
 where
 
@@ -81,11 +81,11 @@
 import           Test.Tasty.HUnit                         (assertFailure)
 
 import qualified Data.List                                as List
+import           Data.String.Interpolate                  (__i)
 import qualified Data.Text.Internal.Search                as T
 import qualified Data.Text.Utf16.Rope.Mixed               as Rope
 import           Development.IDE.Plugin.Completions.Logic (getCompletionPrefixFromRope)
 import           Development.IDE.Plugin.Completions.Types (PosPrefixInfo (..))
-import           NeatInterpolation                        (trimming)
 
 noLiteralCaps :: ClientCapabilities
 noLiteralCaps = def & L.textDocument ?~ textDocumentCaps
