입력 인수를 기반으로 모의 기능 함수
우리는 제공을 위해 Mock 을 한동안 사용 하고 있습니다.
이제 우리는 함수를 조롱하려는 상황이 있습니다.
def foo(self, my_param):
#do something here, assign something to my_result
return my_result
일반적으로 소유하는 조롱하는 방법은 다음과 것입니다 (foo 가의 일부라고 가정)
self.foo = MagicMock(return_value="mocked!")
심지어 foo ()를 몇 번 호출하면 사용할 수 있습니다.
self.foo = MagicMock(side_effect=["mocked once", "mocked twice!"])
이제 입력되는 변수에 특정 값이있을 때 고정 값을 반환하려는 상황에 직면하고 있습니다. "my_param"이 "something"과 같다면 "my_cool_mock"을 반환하고 싶습니다
이 기능 을 위해 mockito에서 사용할 수있는 것입니다.
when(dummy).foo("something").thenReturn("my_cool_mock")
나는 성공하지 못한 채 Mock으로 동일한 것을 달성하는 방법을 어디에 있습니까?
어떤 아이디어?
side_effect
인 함수 경우 해당 함수가 리턴하는 [해석] 모의 리턴을 호출하는을 구석으로입니다. 이side_effect
함수는 모형과 동일한 인수로 호출됩니다. 이를 통해 입력에 따라 호출의 반환 값을 동적으로 사용할 수 있습니다.>>> def side_effect(value): ... return value + 1 ... >>> m = MagicMock(side_effect=side_effect) >>> m(1) 2 >>> m(2) 3 >>> m.mock_calls [call(1), call(2)]
http://www.voidspace.org.uk/python/mock/mock.html#calling
여러 번 호출 된 메소드 로 Python Mock 객체에 것처럼
해결책은 내 자신의 side_effect를 작성하는 것입니다
def my_side_effect(*args, **kwargs):
if args[0] == 42:
return "Called with 42"
elif args[0] == 43:
return "Called with 43"
elif kwarg['foo'] == 7:
return "Foo is seven"
mockobj.mockmethod.side_effect = my_side_effect
그 트릭을 수행
부작용은 함수 ( 람다 함수 일 수도 있음)를 취하고 간단한 경우 다음을 사용할 수 있습니다.
m = MagicMock(side_effect=(lambda x: x+1))
나는 여기서 " 입력 인수를 기반으로 함수를 모의하는 방법 "을 결국 간단한 보조 함수를 만들어 해결했다.
def mock_responses(responses, default_response=None):
return lambda input: responses[input] if input in responses else default_response
지금 :
my_mock.foo.side_effect = mock_responses({'x': 42, 'y': [1,2,3]})
my_mock.goo.side_effect = mock_responses({'hello': 'world'},
default_response='hi')
...
my_mock.foo('x') # => 42
my_mock.foo('y') # => [1,2,3]
my_mock.foo('unknown') # => None
my_mock.goo('hello') # => 'world'
my_mock.goo('ey') # => 'hi'
이것이 누군가를 도울 수 있기를 바랍니다!
다른 방법을 보여주기 위해 :
def mock_isdir(path):
return path in ['/var/log', '/var/log/apache2', '/var/log/tomcat']
with mock.patch('os.path.isdir') as os_path_isdir:
os_path_isdir.side_effect = mock_isdir
다음을 사용할 수도 있습니다 @mock.patch.object
.
모듈 이 데이터베이스에서 읽는 my_module.py
데 사용 pandas
하고 모의 pd.read_sql_table
메서드 ( table_name
인수로 사용) 로이 모듈을 테스트 한다고 가정 해 보겠습니다 .
당신이 할 수있는 일은 db_mock
제공된 인자에 따라 다른 객체를 반환 하는 메소드 를 생성하는 것입니다.
def db_mock(**kwargs):
if kwargs['table_name'] == 'table_1':
# return some DataFrame
elif kwargs['table_name'] == 'table_2':
# return some other DataFrame
테스트 기능에서 다음을 수행합니다.
import my_module as my_module_imported
@mock.patch.object(my_module_imported.pd, "read_sql_table", new_callable=lambda: db_mock)
def test_my_module(mock_read_sql_table):
# You can now test any methods from `my_module`, e.g. `foo` and any call this
# method does to `read_sql_table` will be mocked by `db_mock`, e.g.
ret = my_module_imported.foo(table_name='table_1')
# `ret` is some DataFrame returned by `db_mock`
당신은 또한 사용할 수 있습니다 partial
에서 functools
당신이 매개 변수를 사용하는 함수를 사용하려면하지만 당신은 조롱하는 기능은하지 않습니다. 예 :
def mock_year(year):
return datetime.datetime(year, 11, 28, tzinfo=timezone.utc)
@patch('django.utils.timezone.now', side_effect=partial(mock_year, year=2020))
이것은 매개 변수 (Django의 timezone.now ()와 같은)를 받아들이지 않는 콜 러블을 반환하지만 내 mock_year 함수는 그렇게합니다.
나는 그것의 꽤 오래된 질문을 알고 있으며, 파이썬 lamdba를 사용하여 개선하는 데 도움이 될 수 있습니다.
self.some_service.foo.side_effect = lambda *args:"Called with 42" \
if args[0] == 42 \
else "Called with 42" if args[0] == 43 \
else "Called with 43" if args[0] == 43 \
else "Called with 45" if args[0] == 45 \
else "Called with 49" if args[0] == 49 else None
참고 URL : https://stackoverflow.com/questions/16162015/mocking-python-function-based-on-input-arguments
'IT' 카테고리의 다른 글
입력 필드에 두 개의 레이블이 있습니까? (0) | 2020.07.16 |
---|---|
exception.printStackTrace ()가 왜 나쁜 습관으로 넘어가나요? (0) | 2020.07.16 |
Promise.catch 안에 넣을 수없는 이유는 무엇입니까? (0) | 2020.07.16 |
레일 default_scope를 사용하는 것이 종종 권장되는 이유는 무엇입니까? (0) | 2020.07.16 |
sudo 사건은 어디에보고? (0) | 2020.07.16 |