Тестирование порядка вызовов для ложных объектов с помощью Mox и Python - PullRequest
1 голос
/ 25 октября 2010

Я тестирую функцию, которая получает каркасный объект от одного вспомогательного объекта, модифицирует его с помощью второго помощника и передает измененный объект обратно первому помощнику. Что-то вроде:

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, проверить порядок методов, вызываемых для нескольких mock? Что-то вроде объекта EasyMock MocksControl?

Ответы [ 2 ]

0 голосов
/ 26 октября 2010

Чтобы дать ответ на мой собственный вопрос - в настоящее время у меня это работает, используя побочный эффект, который проверяет порядок вызовов.

Определение класса помощника:

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")
0 голосов
/ 25 октября 2010

Возможно, это не лучшее решение, но вы можете попробовать использовать один макет, который вы дважды дадите тестируемому объекту.После этого вы сможете контролировать порядок вызовов.

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")
...