Having a DirtyReactorException in your tests is a PITA and bug 885342 was that type on annoying bug. Since I use this bug not only to tell others what I’m doing but as a log for myself here it is the way to clean the resources nicely when you are testing your PB clients and servers (I mention PB because we use that, a similar approach can be used with any protocol) inspired by this way more interesting post.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
 
class SaveProtocolServerFactory(PBServerFactory):
    """A PBServerFactory that saves the latest connected client."""
 
    protocolInstance = None
 
    def clientConnectionMade(self, protocol):
        """Keep track of the given protocol."""
        self.protocolInstance = protocol
 
 
class SaveClientFactory(PBClientFactory):
    """Client Factory that knows when we disconnected."""
 
    def __init__(self, connected_d, disconnected_d):
        """Create a new instance."""
        PBClientFactory.__init__(self)
        self.connected_d = connected_d
        self.disconnected_d = disconnected_d
 
    def clientConnectionMade(self, broker):
        """Connection made."""
        PBClientFactory.clientConnectionMade(self, broker)
        self.connected_d.callback(True)
 
    def clientConnectionLost(self, connector, reason, reconnecting=0):
        """Connection lost."""
        self.disconnected_d.callback(True)
 
 
class ServerProtocol(Broker):
    """Server protocol that allows us to clean the tests."""
 
    def connectionLost(self, *a):
        self.factory.onConnectionLost.callback(self)
 
 
class ConnectedTestCase(TestCase):
    """Base test case with a client and a server."""
 
    @defer.inlineCallbacks
    def setUp(self):
        """Set up for the tests."""
        yield super(ConnectedTestCase, self).setUp()
        self.server_disconnected = defer.Deferred()
        self.client_disconnected = defer.Deferred()
        self.listener = None
        self.connector = None
        self.server_factory = None
        self.client_factory = None
 
    def setup_client_server(self, sso_root):
        """Set tests."""
        port = get_sso_pb_port()
        self.listener = self._listen_server(sso_root,
                                self.server_disconnected,
                                port)
        connected = defer.Deferred()
        self.connector = self._connect_client(connected,
                                   self.client_disconnected, port)
        self.addCleanup(self.teardown_client_server)
        return connected
 
    def _listen_server(self, sso_root, d, port):
        """Start listenting."""
        self.server_factory = SaveProtocolServerFactory(sso_root)
        self.server_factory.onConnectionLost = d
        self.server_factory.protocol = ServerProtocol
        return reactor.listenTCP(port, self.server_factory)
 
     def _connect_client(self, d1, d2, port):
        """Connect client."""
        self.client_factory = SaveClientFactory(d1, d2)
        return reactor.connectTCP(LOCALHOST, port, self.client_factory)
 
     def teardown_client_server(self):
         """Clean resources."""
         self.connector.disconnect()
         d = defer.maybeDeferred(self.listener.stopListening)
         return defer.gatherResults([d, self.client_disconnected,
                                               self.server_disconnected])

Read more