diff --git a/src/_zkapauthorizer/tests/test_client_resource.py b/src/_zkapauthorizer/tests/test_client_resource.py
index 75f1803011949b8263682ec129fabcec772b08fd..20174c619151d480046d566e5aa5269887906c89 100644
--- a/src/_zkapauthorizer/tests/test_client_resource.py
+++ b/src/_zkapauthorizer/tests/test_client_resource.py
@@ -732,10 +732,12 @@ class RecoverTests(TestCase):
                     headers_matcher=application_json(),
                     body_matcher=AfterPreprocessing(
                         loads,
-                        Equals({
-                            "stage": "failed",
-                            "failure-reason": reason,
-                        }),
+                        Equals(
+                            {
+                                "stage": "failed",
+                                "failure-reason": reason,
+                            }
+                        ),
                     ),
                 )
             ),
diff --git a/src/_zkapauthorizer/tests/test_recover.py b/src/_zkapauthorizer/tests/test_recover.py
index 8026a6d287af156e30c70c9196dfae4e3e7bf58b..2b50e65aa0bd7d2db3b266b98a76d8b16d68697f 100644
--- a/src/_zkapauthorizer/tests/test_recover.py
+++ b/src/_zkapauthorizer/tests/test_recover.py
@@ -19,15 +19,9 @@ from hypothesis.stateful import (
 )
 from hypothesis.strategies import data, lists, randoms, sampled_from, text
 from testtools import TestCase
-from testtools.matchers import (
-    AfterPreprocessing,
-    Always,
-    Equals,
-    IsInstance,
-    MatchesStructure,
-)
+from testtools.matchers import AfterPreprocessing, Always, Equals, IsInstance
 from testtools.twistedsupport import failed, succeeded
-from twisted.internet.defer import ensureDeferred, inlineCallbacks
+from twisted.internet.defer import Deferred
 from twisted.python.filepath import FilePath
 from zope.interface import implementer
 
@@ -200,7 +194,6 @@ class RecovererTestsMixin:
     def make_recoverer(self, cap: str) -> IRecoverer:
         raise NotImplementedError()
 
-    @inlineCallbacks
     def test_recover(self):
         """
         ````IRecoverer.recover`` loads statements from its path into the cursor
@@ -232,9 +225,13 @@ class RecovererTestsMixin:
         with connect(":memory:") as conn:
             cursor = conn.cursor()
 
-            # Do the recovery.
-            yield ensureDeferred(recoverer.recover(lambda state: None, cap, cursor))
-
+            self.assertThat(
+                # Do the recovery.
+                Deferred.fromCoroutine(
+                    recoverer.recover(lambda state: None, cap, cursor),
+                ),
+                succeeded(Always()),
+            )
             # A snapshot of the recovered database should be the same as a
             # snapshot of the original.
             self.assertThat(
@@ -287,6 +284,10 @@ class SynchronousStorageSnapshotRecovererTests(TestCase, RecovererTestsMixin):
         )
 
 
+class NoSuchCapability(Exception):
+    pass
+
+
 class TahoeLAFSRecovererTests(TestCase, RecovererTestsMixin):
     """
     Tests for ``TahoeLAFSRecoverer``.
@@ -309,19 +310,22 @@ class TahoeLAFSRecovererTests(TestCase, RecovererTestsMixin):
             try:
                 obj = self.grid.download(cap)
             except KeyError:
-                raise Exception("no such capability")
+                raise NoSuchCapability()
             else:
                 outpath.setContent(obj)
 
+        # treq is used by the real download function but we're supplying our
+        # own that doesn't need it, so value here should be irrelevant.  maybe
+        # the http client should be implied by the download API rather than a
+        # parameter it accepts?
         treq = object()
         node_config = config_from_string(self.node_dir.path, "", "")
         return TahoeLAFSRecoverer(treq, node_config, download)
 
-    @inlineCallbacks
     def test_recover_failed(self):
         """
-        If the snapshot data cannot be found then ``IRecoverer.recover`` reports a
-        final state of ``RecoveryStages.failed``.
+        If the snapshot data cannot be found then ``IRecoverer.recover`` raises
+        the underlying exception.
         """
         recoverer = self.make_recoverer()
 
@@ -334,13 +338,20 @@ class TahoeLAFSRecovererTests(TestCase, RecovererTestsMixin):
 
         with connect(":memory:") as conn:
             cursor = conn.cursor()
-
-            yield ensureDeferred(recoverer.recover(record_state, cap, cursor))
-
+            # We expect the recoverer to fail with the exception raised by the
+            # downloader for now.  Later we probably want it to inspect the
+            # exception and sometimes take a different action.  It will
+            # probably never recognize our test-only NoSuchCapability
+            # exception though.
             self.assertThat(
-                states[-1],
-                MatchesStructure(
-                    stage=RecoveryStages.failed,
+                Deferred.fromCoroutine(
+                    recoverer.recover(record_state, cap, cursor),
+                ),
+                failed(
+                    AfterPreprocessing(
+                        lambda f: f.value,
+                        IsInstance(NoSuchCapability),
+                    ),
                 ),
             )
 
@@ -359,7 +370,7 @@ class StatefulRecovererTests(TestCase):
         recoverer = StatefulRecoverer(NullRecoverer())
         with connect(":memory:") as conn:
             cursor = conn.cursor()
-            first = ensureDeferred(recoverer.recover(cap, cursor))
+            first = Deferred.fromCoroutine(recoverer.recover(cap, cursor))
             self.assertThat(
                 first,
                 succeeded(Always()),
@@ -378,7 +389,7 @@ class StatefulRecovererTests(TestCase):
         recoverer = StatefulRecoverer(BrokenRecoverer())
         with connect(":memory:") as conn:
             cursor = conn.cursor()
-            first = ensureDeferred(recoverer.recover(cap, cursor))
+            first = Deferred.fromCoroutine(recoverer.recover(cap, cursor))
             self.assertThat(
                 first,
                 succeeded(Always()),
@@ -394,8 +405,11 @@ class StatefulRecovererTests(TestCase):
         recoverer = StatefulRecoverer(NullRecoverer())
         with connect(":memory:") as conn:
             cursor = conn.cursor()
-            ensureDeferred(recoverer.recover(cap, cursor))
-            second = ensureDeferred(recoverer.recover(cap, cursor))
+            self.assertThat(
+                Deferred.fromCoroutine(recoverer.recover(cap, cursor)),
+                succeeded(Always()),
+            )
+            second = Deferred.fromCoroutine(recoverer.recover(cap, cursor))
             self.assertThat(
                 second,
                 failed(