언 바운드 메소드가있는 클래스를 조롱하려면 어떻게해야합니까? 예를 들어,이 클래스는 @classmethod
과 @staticmethod
있습니다 위의 꽤 많이 내 질문에 설명Python 정적 메소드 및 클래스 메소드 모의 방법
class Calculator(object):
def __init__(self, multiplier):
self._multiplier = multiplier
def multiply(self, n):
return self._multiplier * n
@classmethod
def increment(cls, n):
return n + 1
@staticmethod
def decrement(n):
return n - 1
calculator = Calculator(2)
assert calculator.multiply(3) == 6
assert calculator.increment(3) == 4
assert calculator.decrement(3) == 2
assert Calculator.increment(3) == 4
assert Calculator.decrement(3) == 2
. 다음은 내가 시도한 것들을 보여주는 실례이다.
클래스 Machine
에는 Calculator
의 인스턴스가 포함됩니다. 나는 Machine
을 모의하고 Calculator
으로 테스트 할 것입니다. 모든 기능 위의 코드는 잘 작동
class Machine(object):
def __init__(self, calculator):
self._calculator = calculator
def mult(self, n):
return self._calculator.multiply(n)
def incr_bound(self, n):
return self._calculator.increment(n)
def decr_bound(self, n):
return self._calculator.decrement(n)
def incr_unbound(self, n):
return Calculator.increment(n)
def decr_unbound(self, n):
return Calculator.decrement(n)
machine = Machine(Calculator(3))
assert machine.mult(3) == 9
assert machine.incr_bound(3) == 4
assert machine.incr_unbound(3) == 4
assert machine.decr_bound(3) == 2
assert machine.decr_unbound(3) == 2
: Calculator
의 인스턴스를 통해와 Calculator
클래스를 통해 언 바운드 메소드를 호출 Machine
내 문제를 설명합니다. 다음은 작동하지 않는 부분입니다.
나는 시험 Machine
에서 사용할 Calculator
의 모의를 만들 : 내가 기대했던대로 아래의 단위 테스트에서
from mock import Mock
def MockCalculator(multiplier):
mock = Mock(spec=Calculator, name='MockCalculator')
def multiply_proxy(n):
'''Multiply by 2*multiplier instead so we can see the difference'''
return 2 * multiplier * n
mock.multiply = multiply_proxy
def increment_proxy(n):
'''Increment by 2 instead of 1 so we can see the difference'''
return n + 2
mock.increment = increment_proxy
def decrement_proxy(n):
'''Decrement by 2 instead of 1 so we can see the difference'''
return n - 2
mock.decrement = decrement_proxy
return mock
는, 바인딩 방법
MockCalculator
를 사용합니다. 그러나
Calculator.increment()
및
Calculator.decrement()
에 대한 호출은 여전히
Calculator
를 사용
import unittest
class TestMachine(unittest.TestCase):
def test_bound(self):
'''The bound methods of Calculator are replaced with MockCalculator'''
machine = Machine(MockCalculator(3))
self.assertEqual(machine.mult(3), 18)
self.assertEqual(machine.incr_bound(3), 5)
self.assertEqual(machine.decr_bound(3), 1)
def test_unbound(self):
'''Machine.incr_unbound() and Machine.decr_unbound() are still using
Calculator.increment() and Calculator.decrement(n), which is wrong.
'''
machine = Machine(MockCalculator(3))
self.assertEqual(machine.incr_unbound(3), 4) # I wish this was 5
self.assertEqual(machine.decr_unbound(3), 2) # I wish this was 1
그래서 내가 Calculator.increment()
및 Calculator.decrement()
패치하려고 :
def MockCalculatorImproved(multiplier):
mock = Mock(spec=Calculator, name='MockCalculatorImproved')
def multiply_proxy(n):
'''Multiply by 2*multiplier instead of multiplier so we can see the difference'''
return 2 * multiplier * n
mock.multiply = multiply_proxy
return mock
def increment_proxy(n):
'''Increment by 2 instead of 1 so we can see the difference'''
return n + 2
def decrement_proxy(n):
'''Decrement by 2 instead of 1 so we can see the difference'''
return n - 2
from mock import patch
@patch.object(Calculator, 'increment', increment_proxy)
@patch.object(Calculator, 'decrement', decrement_proxy)
class TestMachineImproved(unittest.TestCase):
def test_bound(self):
'''The bound methods of Calculator are replaced with MockCalculator'''
machine = Machine(MockCalculatorImproved(3))
self.assertEqual(machine.mult(3), 18)
self.assertEqual(machine.incr_bound(3), 5)
self.assertEqual(machine.decr_bound(3), 1)
def test_unbound(self):
'''machine.incr_unbound() and Machine.decr_unbound() should use
increment_proxy() and decrement_proxy(n).
'''
machine = Machine(MockCalculatorImproved(3))
self.assertEqual(machine.incr_unbound(3), 5)
self.assertEqual(machine.decr_unbound(3), 1)
, 언 바운드 방법은 인수로 Calculator
의 인스턴스를 원하는 심지어 패치 후 :
TypeError: unbound method increment_proxy() must be called with Calculator instance as first argument (got int instance instead)
클래스 방법 Calculator.increment()
및 고정 방법 Calculator.decrement()
?
정답입니다. [다른 질문에] 정적 메서드 대 모듈 방법 문제] (http://programmers.stackexchange.com/questions/112137/is-staticmethod-proliferation-a-code-smell)에 대해 논하고 결론은 정적 메서드가 코드 냄새와 모듈 스타일 정의가없고 정적 메소드가 유일한 대체품 인 자바 스타일의 모방. –
이것은 질문에 대답하지 않습니다. 'staticmethod'는 유효한 파이썬 구조이며 모방하는 법을 아는 것이 중요합니다. 정적 방법을 모의 할 수 있다고 생각하면 "다른 일을하십시오"는 정답이 아닙니다. – AnilRedshift