| 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 |