Использование mocking для тестирования производных классов в Python - PullRequest
4 голосов
/ 05 января 2009

У меня есть код, который выглядит так:

import xmlrpclib

class Base(object):
    def __init__(self, server):
        self.conn = xmlrpclib.ServerProxy(server)

    def foo(self):
        return self.conn.do_something()

class Derived(Base):
    def foo(self):
        if Base.foo():
            return self.conn.do_something_else()

Как использовать насмешку, чтобы проверить поведение класса Derived? Я не хочу предполагать, что независимо от того, с чем связывается соединение XML-RPC, оно действительно существует, но я чувствую, что для насмешки над модулем xmlrpclib требуется слишком много знаний о реализации класса Base (который у меня есть для других тестов ).

Или, я думаю, мне стоит использовать насмешку, чтобы проверить это? Если нет, то как бы вы это проверили?

Ответы [ 2 ]

4 голосов
/ 05 января 2009

Вы можете создать поддельный класс ServerProxy и заменить его для тестирования.

Примерно так:

class FakeServerProxy(object):
    def __init__(self, server):
        self.server = server
    def do_something(self):
        pass
    def do_something_else(self):
        pass

def test_derived():
    xmlrpclib.ServerProxy = FakeServerProxy
    derived = Derived(None)
    derived.foo()
3 голосов
/ 28 мая 2009

С помощью некоторого тривиального рефакторинга (извлечен вызов do_something_else) вы можете протестировать логику Derived.foo без необходимости "знать" о XMLRPC.

import xmlrpclib

class Base(object):
    def __init__(self, server):
        self.conn = xmlrpclib.ServerProxy(server)

    def foo(self):
        return self.conn.do_something()

class Derived(Base):
    def foo(self):
        if Base.foo(self):
            return self._bar()
    def _bar(self):
        # moved to its own method so that you
        # you can stub it out to avoid any XMLRPCs
        # actually taking place.
        return self.conn.do_something_else()

import mox

d = Derived('http://deep-thought/unanswered/tagged/life+universe+everything')

m = mox.Mox()
m.StubOutWithMock(Base, 'foo')
m.StubOutWithMock(d, '_bar')
Base.foo(d).AndReturn(True)
d._bar() # Will be called becase Boo.foo returns True.
m.ReplayAll()

d.foo()

m.UnsetStubs()
m.VerifyAll()

В качестве альтернативы или даже предпочтительно, вы можете извлечь вызов do_something_else в метод bar для Base. Это имеет смысл, если мы согласны с тем, что Base инкапсулирует все ваши действия XMLRPC.

В примере используется библиотека-насмешник pymox , но суть остается неизменной независимо от вашего стиля насмешки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...