Тестирование порядка вызовов для ложных объектов с помощью Mox и Python
Я тестирую функцию, которая получает каркасный объект от одного вспомогательного объекта, модифицирует его с помощью второго помощника и передает измененный объект обратно первому помощнику. Что-то вроде:
class ReadModifyUpdate(object):
def __init__(self, store, modifier):
self._store = store
self._modifier = modifier
def modify(key):
record = self._store.read(key)
self._modifier.modify(record)
self._store.update(key, record)
Используя Python и Mox, мы можем проверить это с:
class ReadModifyUpdateTest(mox.MoxTestBase):
def test_modify(self):
mock_record = self.mox.CreateMockAnthing()
mock_store = self.mox.CreateMockAnything()
mock_modifier = self.mox.CreateMockAnything()
mock_store.read("test_key").AndReturn(mock_record)
mock_modifier.modify(mock_record)
mock_store.update("test_key", mock_record)
self.mox.ReplayAll()
updater = ReadModifyUpdate(mock_store, mock_modifier)
updater.modify("test_key")
... но это не улавливает ошибку, из-за которой store.update() непреднамеренно вызывается перед modifier.modify(). Есть ли хороший способ, в Mox, проверить порядок методов, вызываемых для нескольких макетов? Что-то вроде объекта EasyMock MocksControl?
2 ответа
Чтобы дать ответ на мой собственный вопрос - в настоящее время у меня это работает, используя побочный эффект, который проверяет порядок вызовов.
Определение вспомогательного класса:
class OrderedCallSequence(object):
def __init__(self, test_case):
self._expectation_count = 0
self._evaluated = 0
self._test_case = test_case
def assertOrder(self):
self._expectation_count += 1
expected_position = self._expectation_count
def side_effect(*args, **kwargs):
self._evaluated += 1
self._test_case.assertEquals(self._evaluated, expected_position,
msg="Invoked in incorrect sequence")
return side_effect
... контрольный пример становится:
class ReadModifyUpdateTest(mox.MoxTestBase):
def test_modify(self):
mock_record = self.mox.CreateMockAnthing()
mock_store = self.mox.CreateMockAnything()
mock_modifier = self.mox.CreateMockAnything()
sequence = OrderedCallSequence(self)
mock_store.read("test_key").WithSideEffects(sequence.assertOrder()).AndReturn(mock_record)
mock_modifier.modify(mock_record).WithSideEffects(sequence.assertOrder())
mock_store.update("test_key", mock_record).WithSideEffects(sequence.assertOrder())
self.mox.ReplayAll()
updater = ReadModifyUpdate(mock_store, mock_modifier)
updater.modify("test_key")
Возможно, это не лучшее решение, но вы можете попробовать использовать один макет, который вы дважды даете тестируемому объекту. Затем вы можете контролировать порядок вызовов.
class ReadModifyUpdateTest(mox.MoxTestBase):
def test_modify(self):
mock_record = self.mox.CreateMockAnthing()
mock_storeModifier = self.mox.CreateMockAnything()
mock_storeModifier.read("test_key").AndReturn(mock_record)
mock_storeModifier.modify(mock_record)
mock_storeModifier.update("test_key", mock_record)
self.mox.ReplayAll()
updater = ReadModifyUpdate(mock_storeModifier, mock_storeModifier)
updater.modify("test_key")