2014-08-30 14 views
9

Tôi muốn khẳng định rằng một classmethod trong một lớp Python gọi một classmethod với một tập hợp các đối số nhất định. Tôi muốn classmethod giả lập là "spec-ed", vì vậy nó phát hiện nếu nó được gọi với số lượng sai các đối số.Làm thế nào để vá classmethod với autospec trong lớp unmocked?

Khi tôi vá lớp học bằng cách sử dụng patch.object(.., autospec=True, ..), classmethod được thay thế bằng NonCallableMagicMock và tăng lỗi khi tôi cố gắng gọi nó.

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__) 

sản xuất đầu ra:

MagicMock 
NonCallableMagicMock 

Làm thế nào tôi có thể có được một mô hình đặc tả-ed cho _internal_classmethod khi lớp nó thuộc về không được chế giễu?

Trả lời

4

Sử dụng spec thay cho autospec và đặt trực tiếp.

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

mang lại cho tôi

MagicMock 

cho đầu ra.

+6

Điều này giải quyết được vấn đề lấy lại một NonCallableMagicMock, nhưng tiếc là không cung cấp hành vi bắt chữ ký cuộc gọi không khớp trên classmethod giả. Hành vi này là quan trọng bởi vì nó bảo vệ chống lại các thử nghiệm giả mạo mà vượt qua mặc dù mã chính nó bị hỏng, có lẽ bằng cách thay đổi chữ ký cuộc gọi của phương pháp. Tôi nghi ngờ rằng hành vi mà tôi đang tìm kiếm là một phần "autospec" và có lẽ giả lập đó vẫn chưa hỗ trợ điều đó. – scanny

6

Có báo cáo lỗi nổi bật (google code linkpython bug tracker link) để khắc phục vấn đề này. Cho đến khi bản sửa lỗi được kết hợp, bạn có thể thử những điều sau, đã làm việc cho tôi [On 2.7, mặc dù tôi nghĩ rằng nó cũng sẽ hoạt động trong 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 

Sau khỉ, bạn có thể sử dụng mock.patch bình thường và có phương pháp tĩnh và lớp được vá đúng cách.

Các vấn đề liên quan