2014-08-30 33 views
9

Chcę potwierdzić, że jeden classmethod w klasie Python wywołuje inną metodę klasy z pewnym zbiorem argumentów. Chciałbym, aby wyszydzony sposób klasy był "spec-ed", więc wykrywa, czy jest wywoływany z niewłaściwą liczbą argumentów.Jak naprawić metodę class z autospec w niezmkniętej klasie?

Po przyklejeniu metody class za pomocą patch.object(.., autospec=True, ..), metoda class zostaje zastąpiona przez NonCallableMagicMock i powoduje zgłoszenie błędu podczas próby wywołania.

from mock import patch 

class A(object): 

    @classmethod 
    def api_meth(cls): 
     return cls._internal_classmethod(1, 2, 3) 

    @classmethod 
    def _internal_classmethod(cls, n, m, o): 
     return sum(n, m, o) 

with patch.object(A, '_internal_classmethod') as p: 
    print(type(p).__name__) 

with patch.object(A, '_internal_classmethod', autospec=True) as p: 
    print(type(p).__name__) 

produkuje wyjście:

MagicMock 
NonCallableMagicMock 

Jak mogę uzyskać makiety Spec-ED _internal_classmethod gdy klasa należy do nie jest wyśmiewany?

Odpowiedz

4

Użyj spec zamiast autospec i ustaw ją bezpośrednio.

with patch.object(A, '_internal_classmethod', spec=A._internal_classmethod) as p: 
    print(type(p).__name__) 

daje mi

MagicMock 

dla wyjścia.

+6

Rozwiązuje to problem z odzyskiwaniem NonCallableMagicMock, ale niestety nie zapewnia zachowywania się niezgodności sygnatury wywołania w wyśmiewanej metodzie klasy. To zachowanie jest ważne, ponieważ chroni przed wyśmiewanymi testami, które mijają, mimo że sam kod jest uszkodzony, być może zmieniając sygnaturę wywołania metody. Podejrzewam, że zachowanie, którego szukam, jest "częściowym autospeciem" i że być może udawanie jeszcze nie obsługuje tego typu rzeczy. – scanny

6

Istnieje nieaktualny raport o błędzie (google code link i python bug tracker link) w celu rozwiązania tego problemu. Dopóki poprawka nie zostanie włączona, możesz wypróbować następujące rzeczy, które mi się przydały [na 2.7, ale myślę, że działałyby również pod 3.x].

def _patched_callable(obj): 
    "Monkeypatch to allow autospec'ed classmethods and staticmethods." 
    # See https://code.google.com/p/mock/issues/detail?id=241 and 
    # http://bugs.python.org/issue23078 for the relevant bugs this 
    # monkeypatch fixes 
    if isinstance(obj, type): 
     return True 
    if getattr(obj, '__call__', None) is not None: 
     return True 
    if (isinstance(obj, (staticmethod, classmethod)) 
     and mock._callable(obj.__func__)): 
     return True 
    return False 
_patched_callable._old_func = mock._callable 
mock._callable = _patched_callable 

Po monkeypatch, powinieneś być w stanie korzystać z mock.patch normalnie i mają statyc- znych i klasy metod załatane prawidłowo.