회원가입

1. 파이썬 Mocking 모킹

NULL 2022-05-15

 

Mocking 이란?


Unit Test 를 작성하다 보면 데이터베이스 또는 외부 API 에 의존하는 코드를 테스트해야 할 일이 생기기 마련이다.

운영 환경 대비 제약이 많은 테스트 환경에서 실제 데이터베이스 와 연동하거나 실제 외부 API 를 호출하기가 불가능한 경우가 많다.

가능하더라도, 이렇게 외부 서비스에 의존하는 테스트는 해당 서비스(데이터베이스 혹은 외부 API 등)에 문제가 있으면 깨질 수 있으며 실행 속도가 느릴 수밖에 없다.

 

따라서 Unit Test 를 작성할 때 외부에 의존하는 부분을 임의의 가짜로 대체하는 기법이 자주 사용되는데 이를 모킹 Mocking 이라고 한다.

모킹 Mocking 은 외부 서비스에 의존하지 않고 독립적으로 실행이 가능한 Unit Test 를 작성하기 위해 사용되는 테스팅 기법이다.

 

 

unittest.mock 모듈


unittest.mock 모듈은 파이썬 3.3 부터 언어 자체에 기본 내장된 모킹 라이브러리다.

 

따라서 별도의 외부 라이브러리 설치 없이 파이썬 인터프리터에서 아래 코드와 같이 임포트해서 사용할 수 있다.

from unittest.mock import Mock, MagicMock, call

이 모듈을 사용하면 Unit Test 를 작성할 때 코드의 특정 부분을 Mock 객체로 대체할 수 있으며, 해당 Mock 객체가 어떻게 사용되었는지 검증할 수 있다.

 

 

Mock 객체 설정하기


MockingMock 이라고 불리는 가짜 객체를 생성하는 것부터 시작한다.

생성한 가짜 객체 Mock 객체가 어떻게 작동할 지를 지정해 줄 수 있으며 이 Mock 객체는 자신을 상대로 어떤 작업이 일어났는지기억한다.

 

1. return_value

먼저 호출되었을 때 특정 값을 리턴하는 Mock 객체는 return_value 옵션을 이용해서 생성할 수 있다.

from unittest.mock import Mock
mock = Mock(return_value='Hello, Mock!')
mock()

 

2. side_effect 예외 Exception

반면에 호출되었을 때 예외가 발생하는 Mock 객체는 side_effect 옵션을 이용해서 생성할 수 있다.

mock = Mock(side_effect=Exception('Oops!'))
mock()

 

3. side_effect 리스트

side_effect 옵션에 리스트를 넘기면 Mock 객체가 호출될 때마다 매번 다른 값을 리턴할 수도 있다.

mock = Mock(side_effect=[1, 2, 3])
mock()
mock()
mock()
mock()

 

4. side_effect 함수 (lambda)

side_effect 옵션에 함수를 넘기면 Mock 객체를 호출했을 때 주어진 인자에 따라 다른 값을 리턴할 수 있다.

mock = Mock(side_effect=lambda x: x * 10)
mock(1)
mock(2)

 

5. 기본 생성자로 객체 생성 후 return_value, side_effect 적용

return_valueside_effect 옵션은 꼭 Mock() 생성자의 인자로 넘어갈 필요는 없다.

아래와 같이 Mock 객체를 생성한 후, 얼마든지 옵션값은 바꿀 수 있다.

mock = Mock()
mock.return_value = 1
mock()

mock.return_value = 2
mock()

 

6. Mock 객체에 인스턴스 변수를 설정하면 새로운 Mock

Mock 객체는 함수처럼 바로 호출(mock())을 할 수도 있지만, 객체처럼 속성도 가질 수 있는데 각 속성은 새로운 Mock 이 된다.

따라서 아래와 같이 특정 속성에 값을 할당할 수도 있고, 특정 메서드의 리턴 값을 지정해 줄 수도 있다.

mock = Mock()
mock.attribute = 'ATTRIBUTE'
mock.attribute

mock.method.return_value = 'METHOD RETURN VALUE'
mock.method()

mock.method.return_value 를 하여 mock 객체 안에 method 이름을 가진 속성은 Mock 객체이기 때문에 method.return_value 를 설정하면 mock.method() 처럼 이용할 수 있다는 뜻이다.

 

이렇게 Mock 객체의 속성이나 메서드도 또 다른 Mock 객체가 된다는 점을 잘 활용하면 유연한 Mocking 이 가능해진다.

 

 

참고 링크: https://www.daleseo.com/python-unittest-mock/

0 0
테스트
테스트를 작성해야 하는 이유는 정말 너무 많다. 개발 관점으로 다양한 테스팅에 과정에 대해 필자가 공부한 것을 토대로 포스팅한 게시판이다.
Yesterday: 750
Today: 554