From aed51a5f2e536a19caa69e390778c20be9c3b593 Mon Sep 17 00:00:00 2001 From: smiddlek Date: Fri, 3 Sep 2010 17:00:55 +0000 Subject: + Fix for checking the method signature of unbound functions when keyword args are passed as positional. With tests. + Made the comparator more robust by catching exceptions and returning False git-svn-id: http://pymox.googlecode.com/svn/trunk@60 b1010a0a-674b-0410-b734-77272b80c875 --- mox.py | 26 +++++++++++---- mox_test.py | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++---- mox_test_helper.py | 15 +++++++++ 3 files changed, 123 insertions(+), 14 deletions(-) diff --git a/mox.py b/mox.py index c5f8bf0..6b37f37 100755 --- a/mox.py +++ b/mox.py @@ -902,7 +902,7 @@ class MethodSignatureChecker(object): # correct, this will cause extra executions of the function. if inspect.ismethod(self._method): # The extra param accounts for the bound instance. - if len(params) == len(self._required_args) + 1: + if len(params) > len(self._required_args): expected = getattr(self._method, 'im_class', None) # Check if the param is an instance of the expected class, @@ -1169,7 +1169,7 @@ class MockMethod(object): """Move this method into group of calls which may be called multiple times. A group of repeating calls must be defined together, and must be executed in - full before the next expected mehtod can be called. + full before the next expected method can be called. Args: group_name: the name of the unordered group. @@ -1245,7 +1245,10 @@ class Comparator: raise NotImplementedError, 'method must be implemented by a subclass.' def __eq__(self, rhs): - return self.equals(rhs) + try: + return self.equals(rhs) + except Exception: + return False def __ne__(self, rhs): return not self.equals(rhs) @@ -1348,7 +1351,7 @@ class IsAlmost(Comparator): try: return round(rhs-self._float_value, self._places) == 0 - except TypeError: + except Exception: # This is probably because either float_value or rhs is not a number. return False @@ -1419,7 +1422,10 @@ class Regex(Comparator): bool """ - return self.regex.search(rhs) is not None + try: + return self.regex.search(rhs) is not None + except Exception: + return False def __repr__(self): s = '' % str(self._key) @@ -1489,7 +1498,10 @@ class Not(Comparator): bool """ - return not self._predicate.equals(rhs) + try: + return not self._predicate.equals(rhs) + except Exception: + return False def __repr__(self): return '' % self._predicate diff --git a/mox_test.py b/mox_test.py index 47acd6a..a18b0f5 100755 --- a/mox_test.py +++ b/mox_test.py @@ -1568,7 +1568,7 @@ class MoxTest(unittest.TestCase): self.assertEquals('foo', actual) self.assertTrue(type(test_obj.OtherValidCall) is method_type) - def testStubOutMethod_CalledAsUnboundMethod_Comparator(self): + def testStubOutMethod_Unbound_Comparator(self): instance = TestClass() self.mox.StubOutWithMock(TestClass, 'OtherValidCall') @@ -1581,7 +1581,7 @@ class MoxTest(unittest.TestCase): self.mox.UnsetStubs() self.assertEquals('foo', actual) - def testStubOutMethod_CalledAsUnboundMethod_Subclass_Comparator(self): + def testStubOutMethod_Unbound_Subclass_Comparator(self): self.mox.StubOutWithMock(mox_test_helper.TestClassFromAnotherModule, 'Value') mox_test_helper.TestClassFromAnotherModule.Value( mox.IsA(mox_test_helper.ChildClassFromAnotherModule)).AndReturn('foo') @@ -1594,7 +1594,7 @@ class MoxTest(unittest.TestCase): self.mox.UnsetStubs() self.assertEquals('foo', actual) - def testStubOuMethod_UnboundWithOptionalParams(self): + def testStubOuMethod_Unbound_WithOptionalParams(self): self.mox = mox.Mox() self.mox.StubOutWithMock(TestClass, 'OptionalArgs') TestClass.OptionalArgs(mox.IgnoreArg(), foo=2) @@ -1606,7 +1606,7 @@ class MoxTest(unittest.TestCase): self.mox.VerifyAll() self.mox.UnsetStubs() - def testStubOutMethod_CalledAsUnboundMethod_ActualInstance(self): + def testStubOutMethod_Unbound_ActualInstance(self): instance = TestClass() self.mox.StubOutWithMock(TestClass, 'OtherValidCall') @@ -1619,7 +1619,7 @@ class MoxTest(unittest.TestCase): self.mox.UnsetStubs() self.assertEquals('foo', actual) - def testStubOutMethod_CalledAsUnboundMethod_DifferentInstance(self): + def testStubOutMethod_Unbound_DifferentInstance(self): instance = TestClass() self.mox.StubOutWithMock(TestClass, 'OtherValidCall') @@ -1633,7 +1633,42 @@ class MoxTest(unittest.TestCase): self.mox.VerifyAll() self.mox.UnsetStubs() - def testStubOutMethod_CalledAsBoundMethod(self): + def testStubOutMethod_Unbound_NamedUsingPositional(self): + """Check positional parameters can be matched to keyword arguments.""" + self.mox.StubOutWithMock(mox_test_helper.ExampleClass, 'NamedParams') + instance = mox_test_helper.ExampleClass() + mox_test_helper.ExampleClass.NamedParams(instance, 'foo', baz=None) + self.mox.ReplayAll() + + mox_test_helper.ExampleClass.NamedParams(instance, 'foo', baz=None) + + self.mox.VerifyAll() + self.mox.UnsetStubs() + + def testStubOutMethod_Unbound_NamedUsingPositional_SomePositional(self): + """Check positional parameters can be matched to keyword arguments.""" + self.mox.StubOutWithMock(mox_test_helper.ExampleClass, 'TestMethod') + instance = mox_test_helper.ExampleClass() + mox_test_helper.ExampleClass.TestMethod(instance, 'one', 'two', 'nine') + self.mox.ReplayAll() + + mox_test_helper.ExampleClass.TestMethod(instance, 'one', 'two', 'nine') + + self.mox.VerifyAll() + self.mox.UnsetStubs() + + def testStubOutMethod_Unbound_SpecialArgs(self): + self.mox.StubOutWithMock(mox_test_helper.ExampleClass, 'SpecialArgs') + instance = mox_test_helper.ExampleClass() + mox_test_helper.ExampleClass.SpecialArgs(instance, 'foo', None, bar='bar') + self.mox.ReplayAll() + + mox_test_helper.ExampleClass.SpecialArgs(instance, 'foo', None, bar='bar') + + self.mox.VerifyAll() + self.mox.UnsetStubs() + + def testStubOutMethod_Bound_SimpleTest(self): t = self.mox.CreateMock(TestClass) t.MethodWithArgs(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn('foo') @@ -1645,6 +1680,53 @@ class MoxTest(unittest.TestCase): self.mox.UnsetStubs() self.assertEquals('foo', actual) + def testStubOutMethod_Bound_NamedUsingPositional(self): + """Check positional parameters can be matched to keyword arguments.""" + self.mox.StubOutWithMock(mox_test_helper.ExampleClass, 'NamedParams') + instance = mox_test_helper.ExampleClass() + instance.NamedParams('foo', baz=None) + self.mox.ReplayAll() + + instance.NamedParams('foo', baz=None) + + self.mox.VerifyAll() + self.mox.UnsetStubs() + + def testStubOutMethod_Bound_NamedUsingPositional_SomePositional(self): + """Check positional parameters can be matched to keyword arguments.""" + self.mox.StubOutWithMock(mox_test_helper.ExampleClass, 'TestMethod') + instance = mox_test_helper.ExampleClass() + instance.TestMethod(instance, 'one', 'two', 'nine') + self.mox.ReplayAll() + + instance.TestMethod(instance, 'one', 'two', 'nine') + + self.mox.VerifyAll() + self.mox.UnsetStubs() + + def testStubOutMethod_Bound_SpecialArgs(self): + self.mox.StubOutWithMock(mox_test_helper.ExampleClass, 'SpecialArgs') + instance = mox_test_helper.ExampleClass() + instance.SpecialArgs(instance, 'foo', None, bar='bar') + self.mox.ReplayAll() + + instance.SpecialArgs(instance, 'foo', None, bar='bar') + + self.mox.VerifyAll() + self.mox.UnsetStubs() + + def testStubOut_SignatureMatching_init_(self): + self.mox.StubOutWithMock(mox_test_helper.ExampleClass, '__init__') + mox_test_helper.ExampleClass.__init__(mox.IgnoreArg()) + self.mox.ReplayAll() + + # Create an instance of a child class, which calls the parent + # __init__ + mox_test_helper.ChildExampleClass() + + self.mox.VerifyAll() + self.mox.UnsetStubs() + def testStubOutClass_OldStyle(self): """Test a mocked class whose __init__ returns a Mock.""" self.mox.StubOutWithMock(mox_test_helper, 'TestClassFromAnotherModule') @@ -2061,7 +2143,7 @@ class TestClass: def OtherValidCall(self): pass - def OptionalArgs(self, foo=None): + def OptionalArgs(self, foo='boom'): pass def ValidCallWithArgs(self, *args, **kwargs): diff --git a/mox_test_helper.py b/mox_test_helper.py index 0ccd484..5ac989f 100755 --- a/mox_test_helper.py +++ b/mox_test_helper.py @@ -123,5 +123,20 @@ def MyTestFunction(one, two, nine=None): class ExampleClass(object): + def __init__(self, foo='bar'): + pass + def TestMethod(self, one, two, nine=None): pass + + def NamedParams(self, ignore, foo='bar', baz='qux'): + pass + + def SpecialArgs(self, *args, **kwargs): + pass + + +# This class is used to test stubbing out __init__ of a parent class. +class ChildExampleClass(ExampleClass): + def __init__(self): + ExampleClass.__init__(self) -- cgit v1.2.1