2014-03-27 2 views
19

나는 콜 순서를 테스트하려고하는 세 가지 기능이 있습니다. 여러 개의 모크에서 호출 순서 확인

는의는 내가 그 B를 확인하려면
# module.py  

def a(*args): 
    # do the first thing 

def b(*args): 
    # do a second thing 

def c(*args): 
    # do a third thing 


def main_routine(): 
    a_args = ('a') 
    b_args = ('b') 
    c_args = ('c') 

    a(*a_args) 
    b(*b_args) 
    c(*c_args) 

이 후라고 다음, 및 C 전에 모듈 module.py에 내가 가진한다고 가정 해 봅시다. 그래서, B와 C의 각각에 대한 모의를 얻는 것은 쉽다 :
# tests.py 

@mock.patch('module.a') 
@mock.patch('module.b') 
@mock.patch('module.c') 
def test_main_routine(c_mock, b_mock, a_mock): 
    # test all the things here 

이 individial 모의 객체의 각 호출되는 것을 확인하는 것은 너무 쉽다. 상대방과의 상대적인 순서를 어떻게 확인합니까?

call_args_list은 각 모의 용으로 별도로 관리되므로 작동하지 않습니다.

나는 호출의 각 로그온 할 때 부작용을 사용하여 시도했다 :

calls = [] 
def register_call(*args): 
    calls.append(mock.call(*args)) 
    return mock.DEFAULT 

a_mock.side_effect = register_call 
b_mock.side_effect = register_call 
c_mock.side_effect = register_call 

을하지만 이것은 단지 나에게 모의 객체가 호출 된 인수를 제공,하지만 실제 모의 통화가 만들어 졌다고 반대. 조금 더 많은 로직을 추가 할 수 있습니다 :

# tests.py 
from functools import partial 

def register_call(*args, **kwargs): 
    calls.append(kwargs.pop('caller', None), mock.call(*args, **kwargs)) 
    return mock.DEFAULT 

a_mock.side_effect = partial(register_call, caller='a') 
b_mock.side_effect = partial(register_call, caller='b') 
c_mock.side_effect = partial(register_call, caller='c') 

그리고 그게 일을 끝내는 것 같습니다. 더 좋은 방법이 있습니까? 이미 API에서 누락 된 부분이있는 것처럼 느껴집니다.

답변

20

Mock 관리자를 정의하고 attach_mock()을 통해 모의을 첨부하십시오. 그런 다음 mock_calls 확인 :

@patch('module.a') 
@patch('module.b') 
@patch('module.c') 
def test_main_routine(c, b, a): 
    manager = Mock() 
    manager.attach_mock(a, 'a') 
    manager.attach_mock(b, 'b') 
    manager.attach_mock(c, 'c') 

    module.main_routine() 

    expected_calls = [call.a('a'), call.b('b'), call.c('c')] 
    assert manager.mock_calls == expected_calls 

그냥 작동하는지 테스트하기 위해, 추가가 AssertionError를 던졌습니다 참조 main_routine() 함수 호출 함수의 순서를 변경합니다.

도움이 Tracking order of calls and less verbose call assertions

희망에 더 많은 예제를 참조하십시오.

+1

중요한주의 사항 - 패치 내부에 autospec = True를 설정하지 마십시오 (...). autospec = True로 설정하면 attach_mock이 올바르게 작동하지 않습니다. 예제에는 자동 기록이 없지만 실생활 테스트 케이스에는 종종 존재합니다. –