OLD | NEW |
| (Empty) |
1 # Copyright (c) 2007 Twisted Matrix Laboratories. | |
2 # See LICENSE for details. | |
3 | |
4 """ | |
5 Tests for L{twisted.python.monkey}. | |
6 """ | |
7 | |
8 from twisted.trial import unittest | |
9 from twisted.python.monkey import MonkeyPatcher | |
10 | |
11 | |
12 class TestObj: | |
13 def __init__(self): | |
14 self.foo = 'foo value' | |
15 self.bar = 'bar value' | |
16 self.baz = 'baz value' | |
17 | |
18 | |
19 class MonkeyPatcherTest(unittest.TestCase): | |
20 """ | |
21 Tests for L{MonkeyPatcher} monkey-patching class. | |
22 """ | |
23 | |
24 def setUp(self): | |
25 self.testObject = TestObj() | |
26 self.originalObject = TestObj() | |
27 self.monkeyPatcher = MonkeyPatcher() | |
28 | |
29 | |
30 def test_empty(self): | |
31 """ | |
32 A monkey patcher without patches shouldn't change a thing. | |
33 """ | |
34 self.monkeyPatcher.patch() | |
35 | |
36 # We can't assert that all state is unchanged, but at least we can | |
37 # check our test object. | |
38 self.assertEquals(self.originalObject.foo, self.testObject.foo) | |
39 self.assertEquals(self.originalObject.bar, self.testObject.bar) | |
40 self.assertEquals(self.originalObject.baz, self.testObject.baz) | |
41 | |
42 | |
43 def test_constructWithPatches(self): | |
44 """ | |
45 Constructing a L{MonkeyPatcher} with patches should add all of the | |
46 given patches to the patch list. | |
47 """ | |
48 patcher = MonkeyPatcher((self.testObject, 'foo', 'haha'), | |
49 (self.testObject, 'bar', 'hehe')) | |
50 patcher.patch() | |
51 self.assertEquals('haha', self.testObject.foo) | |
52 self.assertEquals('hehe', self.testObject.bar) | |
53 self.assertEquals(self.originalObject.baz, self.testObject.baz) | |
54 | |
55 | |
56 def test_patchExisting(self): | |
57 """ | |
58 Patching an attribute that exists sets it to the value defined in the | |
59 patch. | |
60 """ | |
61 self.monkeyPatcher.addPatch(self.testObject, 'foo', 'haha') | |
62 self.monkeyPatcher.patch() | |
63 self.assertEquals(self.testObject.foo, 'haha') | |
64 | |
65 | |
66 def test_patchNonExisting(self): | |
67 """ | |
68 Patching a non-existing attribute fails with an C{AttributeError}. | |
69 """ | |
70 self.monkeyPatcher.addPatch(self.testObject, 'nowhere', | |
71 'blow up please') | |
72 self.assertRaises(AttributeError, self.monkeyPatcher.patch) | |
73 | |
74 | |
75 def test_patchAlreadyPatched(self): | |
76 """ | |
77 Adding a patch for an object and attribute that already have a patch | |
78 overrides the existing patch. | |
79 """ | |
80 self.monkeyPatcher.addPatch(self.testObject, 'foo', 'blah') | |
81 self.monkeyPatcher.addPatch(self.testObject, 'foo', 'BLAH') | |
82 self.monkeyPatcher.patch() | |
83 self.assertEquals(self.testObject.foo, 'BLAH') | |
84 self.monkeyPatcher.restore() | |
85 self.assertEquals(self.testObject.foo, self.originalObject.foo) | |
86 | |
87 | |
88 def test_restoreTwiceIsANoOp(self): | |
89 """ | |
90 Restoring an already-restored monkey patch is a no-op. | |
91 """ | |
92 self.monkeyPatcher.addPatch(self.testObject, 'foo', 'blah') | |
93 self.monkeyPatcher.patch() | |
94 self.monkeyPatcher.restore() | |
95 self.assertEquals(self.testObject.foo, self.originalObject.foo) | |
96 self.monkeyPatcher.restore() | |
97 self.assertEquals(self.testObject.foo, self.originalObject.foo) | |
98 | |
99 | |
100 def test_runWithPatchesDecoration(self): | |
101 """ | |
102 runWithPatches should run the given callable, passing in all arguments | |
103 and keyword arguments, and return the return value of the callable. | |
104 """ | |
105 log = [] | |
106 | |
107 def f(a, b, c=None): | |
108 log.append((a, b, c)) | |
109 return 'foo' | |
110 | |
111 result = self.monkeyPatcher.runWithPatches(f, 1, 2, c=10) | |
112 self.assertEquals('foo', result) | |
113 self.assertEquals([(1, 2, 10)], log) | |
114 | |
115 | |
116 def test_repeatedRunWithPatches(self): | |
117 """ | |
118 We should be able to call the same function with runWithPatches more | |
119 than once. All patches should apply for each call. | |
120 """ | |
121 def f(): | |
122 return (self.testObject.foo, self.testObject.bar, | |
123 self.testObject.baz) | |
124 | |
125 self.monkeyPatcher.addPatch(self.testObject, 'foo', 'haha') | |
126 result = self.monkeyPatcher.runWithPatches(f) | |
127 self.assertEquals( | |
128 ('haha', self.originalObject.bar, self.originalObject.baz), result) | |
129 result = self.monkeyPatcher.runWithPatches(f) | |
130 self.assertEquals( | |
131 ('haha', self.originalObject.bar, self.originalObject.baz), | |
132 result) | |
133 | |
134 | |
135 def test_runWithPatchesRestores(self): | |
136 """ | |
137 C{runWithPatches} should restore the original values after the function | |
138 has executed. | |
139 """ | |
140 self.monkeyPatcher.addPatch(self.testObject, 'foo', 'haha') | |
141 self.assertEquals(self.originalObject.foo, self.testObject.foo) | |
142 self.monkeyPatcher.runWithPatches(lambda: None) | |
143 self.assertEquals(self.originalObject.foo, self.testObject.foo) | |
144 | |
145 | |
146 def test_runWithPatchesRestoresOnException(self): | |
147 """ | |
148 Test runWithPatches restores the original values even when the function | |
149 raises an exception. | |
150 """ | |
151 def _(): | |
152 self.assertEquals(self.testObject.foo, 'haha') | |
153 self.assertEquals(self.testObject.bar, 'blahblah') | |
154 raise RuntimeError, "Something went wrong!" | |
155 | |
156 self.monkeyPatcher.addPatch(self.testObject, 'foo', 'haha') | |
157 self.monkeyPatcher.addPatch(self.testObject, 'bar', 'blahblah') | |
158 | |
159 self.assertRaises(RuntimeError, self.monkeyPatcher.runWithPatches, _) | |
160 self.assertEquals(self.testObject.foo, self.originalObject.foo) | |
161 self.assertEquals(self.testObject.bar, self.originalObject.bar) | |
OLD | NEW |