조롱이란 무엇입니까?


답변:


598

프롤로그 : 사전에서 명사 모형 을 찾아 보면 단어의 정의 중 하나가 모방으로 만들어진 것임을 알 수 있습니다.


모의는 주로 단위 테스트에 사용됩니다. 테스트중인 객체는 다른 (복잡한) 객체에 종속 될 수 있습니다. 객체의 비헤이비어를 분리하려면 실제 객체의 비헤이비어를 시뮬레이션하는 모의 객체로 다른 객체를 교체하십시오. 이것은 실제 객체가 단위 테스트에 통합하기에 실용적이지 않은 경우에 유용합니다.

요컨대, 조롱은 실제 객체의 동작을 시뮬레이션하는 객체를 만듭니다.


때로는 스터 빙이 아닌 조롱 을 구별하고 싶을 수도 있습니다 . 이 주제에 대해 약간의 의견 차이가있을 수 있지만 스텁에 대한 나의 정의는 "최소한"시뮬레이션 된 객체입니다. 스터브는 테스트중인 개체가 테스트를 실행할 수 있도록 충분한 동작을 구현합니다.

모의는 스터브와 비슷하지만 테스트는 테스트중인 객체가 예상대로 모의를 호출하는지 확인합니다. 테스트의 일부는 모의가 올바르게 사용되었는지 확인하는 것입니다.

예를 들면 다음과 같습니다. 레코드 저장을위한 간단한 메모리 내 구조를 구현하여 데이터베이스를 스텁 할 수 있습니다. 그런 다음 테스트중인 오브젝트는 데이터베이스 스텁에서 레코드를 읽고 기록하여 테스트를 실행할 수 있습니다. 이것은 데이터베이스와 관련이없는 오브젝트의 일부 동작을 테스트 할 수 있으며 데이터베이스 스텁은 테스트 실행을 위해 포함됩니다.

대신 테스트중인 오브젝트가 특정 데이터를 데이터베이스에 쓰는지 확인하려면 데이터베이스를 조롱해야합니다. 그런 다음 테스트는 데이터베이스 모의에 작성된 내용에 대한 어설 션을 통합합니다.


18
이것은 좋은 대답이지만, 조롱이라는 개념을 불필요하게 객체로 제한 합니다 . "object"를 "unit"으로 바꾸면 더 일반적입니다.
Rogério

1
스텁과 모의 차이점을 이해합니다. 스텁으로 사례를 테스트하고 통과 한 경우 이미 스텁을 사용하고 있다는 결론을 내릴 수 없으므로 더 이상 확인이 필요하지 않습니다 .

91

다른 답변은 조롱이 무엇인지 설명합니다. 다른 예를 들어 설명해 드리겠습니다 . 그리고 믿습니다. 실제로 생각보다 훨씬 간단합니다.

tl; dr 원래 클래스의 인스턴스입니다. 여기에는 다른 데이터가 주입되므로 주입 된 부품 을 테스트하지 않고 구현 세부 사항 테스트 에만 집중합니다 . 말고 클래스 / 함수 하십시오.

간단한 예 :

class Foo {
    func add (num1: Int, num2: Int) -> Int { // Line A 
        return num1 + num2 // Line B
    }
}

let unit = Foo() // unit under test
assertEqual(unit.add(1,5),6)

보시다시피, 나는 LineA를 테스트하지 않습니다. 즉 입력 매개 변수를 확인하지 않습니다. num1, num2가 정수인지 확인하지 않습니다. 나는 그것에 대해 어떤 주장도 없다.

LineB (내 구현 ) 가 모의 값을 제공 하는지 확인하기 만 테스트 1하고 있습니다.5 나는 예상대로하고있다.

분명히 말해서 이것은 훨씬 더 복잡해질 수 있습니다. 매개 변수는 개인, 주소와 같은 사용자 정의 오브젝트이거나 구현 세부 사항이 둘 이상일 수 있습니다.+ . 그러나 테스트 논리는 동일합니다.

비 코딩 예 :

공항 보안을 위해 전자 장치의 유형과 브랜드 이름을 식별하는 시스템을 구축한다고 가정합니다. 기계는 카메라로 보는 것을 처리하여이를 수행합니다.

이제 관리자가 문을 걸어 단위 테스트를 요청합니다.

그런 다음 개발자는 MacBook Pro, Google Nexus, 바나나, iPad 등 1000 개의 실제 개체를 가져 와서 테스트하여 모두 작동하는지 확인할 수 있습니다.

그러나 당신은 또한 조롱 을 사용할 수 있습니다 동일한 모양의 MacBook Pro (실제 내부 부품 없음) 또는 플라스틱 바나나와 같은 물건 . 1000 개의 실제 랩톱 및 썩은 바나나에 투자하지 않아도됩니다.

요점은 바나나가 가짜인지 테스트하지 않는 것입니다. 랩톱이 가짜인지 테스트하지도 않습니다. 컴퓨터에 바나나가 표시 not an electronic device되고 MacBook Pro에 대해서는 다음과 같이 표시 Laptop, Apple됩니다. 기계의 탐지 결과는 가짜 / 모의 전자 장치와 실제 전자 장치에서 동일해야합니다.

위에서 언급 한 논리는 실제 코드의 단위 테스트에도 적용됩니다. 그것은 함수가 실제 입력 (및 상호 작용) 에서 얻 거나 모의 한 실제 값과 동일하게 작동해야한다는 것입니다단위 테스트 중에 주입 한 값. 또한 실제 바나나 또는 MacBook을 사용하지 않는 방법과 마찬가지로 단위 테스트 (및 조롱)를 사용하면 서버가 500, 403, 200 등의 상태 코드를 반환하는 작업을 수행하지 않아도됩니다 (강제 500을 트리거하는 서버는 서버가 중단 된 경우에만, 200은 서버가 가동 된 경우에만 가능합니다. 서버를 위아래로 전환하는 사이에 10 초 동안 계속 기다려야하는 경우 100 개의 네트워크 중심 테스트를 실행하기가 어렵습니다). 대신 상태 코드 500, 200, 403 등으로 응답을 주입 / 모의하고 주입 / 모의 값으로 장치 / 기능을 테스트합니다.

코딩 예 :

iOS 애플리케이션을 작성 중이고 네트워크 호출이 있다고 가정 해 봅시다. 당신의 임무는 애플리케이션 을 테스트하는 입니다. 네트워크 호출이 예상대로 작동하는지 테스트 / 식별하는 것은 귀하의 책임이 아닙니다. 그것을 테스트하는 것은 다른 당사자의 (서버 팀) 책임입니다. 이 (네트워크) 종속성을 제거하고 그 주위 에서 작동하는 모든 코드를 계속 테스트해야합니다 .

네트워크 호출은 JSON 응답으로 다른 상태 코드 404, 500, 200, 303 등을 반환 할 수 있습니다.

앱은 모든 앱에서 작동한다고 가정 합니다 (오류의 경우 앱에서 예상 오류가 발생 함). 조롱으로하는 일은 '실제 네트워크 호출을 만들고 네트워크 응답을 기다리지 않고 '실제 와 같은 네트워크 응답 (JSON 파일의 200 코드와 유사)을 만들고 코드 테스트하는 것 입니다. 모든 종류의 네트워크 응답에 대해 네트워크 응답을 수동으로 하드 코딩 / 반환하고 앱이 예상대로 작동하는지 확인합니다. (당신은 결코 그 책임이 아니기 때문에, 잘못된 데이터와 200을 테스트 /지지 않습니다, 귀하의 책임 테스트하는 것입니다 귀하의 정확한 (200)와 응용 프로그램을, 또는 400, 500, 당신 테스트의 경우 앱 올바른 오류가 발생하는 경우)

현실과 유사한 상상을 창조하는 것을 조롱이라고합니다.

이렇게하려면 원래 코드를 사용할 수 없습니다 (원래 코드에는 미리 삽입 된 응답이 없습니다.)? 당신은 해야한다 그것에 무언가를 추가 분사 / 일반적으로 필요하지 않은 그 더미 데이터 (또는 클래스의 일부)를 삽입합니다.

당신이 인스턴스를 원래 클래스를 만들고 어떤 추가 그래서 당신이 그것을 필요하고 테스트 (여기에 네트워크 HttpResponse에, 데이터 또는 실패의 경우에있는 올바른 Errorstring이, HttpResponse에 통과) 조롱 클래스를.

간단히 말하면, 조롱은 테스트 대상 을 단순화 하고 제한 하고 클래스가 의존하는 것을 피드하는 것입니다. 이 예제에서는 테스트를 피할 네트워크는 자신을 호출 , 대신 시험 예상대로 앱 작동 여부를 주입 출력 / 답변으로 -에 의해 조롱 클래스

말할 것도없이, 각 네트워크 응답을 개별적으로 테스트하십시오.


이제 내가 항상 생각했던 질문은 다음과 같습니다. 계약 / 종료 지점 및 기본적으로 API의 JSON 응답이 지속적으로 업데이트됩니다. 이를 고려하여 단위 테스트를 작성하려면 어떻게해야합니까?

이에 대해 자세히 설명하려면 모델에 키 / 필드라는 이름이 필요하다고 가정 해 보겠습니다 username. 이것을 테스트하고 테스트를 통과합니다. 2 주 후 백엔드는 키 이름을로 변경합니다 id. 테스트는 여전히 통과합니다. 권리? 또는 아닙니다?

모의 내용을 업데이트하는 것은 백엔드 개발자의 책임입니까? 업데이트 된 모형을 제공하는 것이 당사 계약의 일부 여야합니까?

위의 문제에 대한 대답은 다음과 같습니다. 단위 테스트 + 클라이언트 측 개발자로서의 개발 프로세스는 오래된 모의 응답을 포착해야합니다. 어떻게 물어 보면? 정답은 :

우리의 실제 응용 프로그램은 업데이트 된 API를 사용하지 않으면 실패합니다 (또는 실패하지는 않지만 원하는 동작을하지 못합니다). 그래서 실패하면 ... 개발 코드를 변경합니다. 다시 테스트에 실패합니다. 수정해야합니다. (실제로 TDD 프로세스를 올바르게 수행하려면 테스트를 작성하지 않으면 필드에 대한 코드를 작성해서는 안됩니다. 실패한 다음 실제 개발 코드를 작성하여 작성하십시오.)

이것은 백엔드가 "모의를 업데이트했습니다"라고 말할 필요가 없다는 것을 의미합니다. 결국 코드 개발 / 디버깅을 통해 발생합니다. ‌ّ 개발 과정의 모든 부분이기 때문에! 백엔드가 모의 응답을 제공한다면 더 쉽습니다.

이것에 대한 나의 요점은 ( 모의 API 응답 업데이트를 자동화 할 수없는 경우) JSON의 수동 업데이트 및 짧은 회의를 통해 값이 최신 상태인지 확인하는 프로세스의 일부가 될 것입니다.

이 섹션은 CocoaHead 밋업 그룹의 느슨한 토론 덕분에 작성되었습니다


iOS 개발자 만 해당 :

조롱의 좋은 예는 Natasha Muraschev의 실용 프로토콜 지향 강연 입니다. 슬라이드가 실제 비디오와 동기화되지 않을 수 있지만 18:30 분으로 건너 뛰십시오. 🤷‍♂️

나는이 부분을 대본에서 정말 좋아한다.

이것은 테스트 중이므로 ...에서 get함수 Gettable가 호출 되는지 확인 하고 함수가 이론적으로 어디서나 음식 항목 배열을 할당 할 수 있기 때문에 확인하고 싶습니다 . 호출되는지 확인해야합니다.


3
좋은 예,이 특정 예제에서 서브 클래스는 모의 역할을하지만이 예제는 스터 빙도 사용한다고 덧붙입니다. 하드 코딩 된 JSON 응답은 스텁 된 응답으로 간주됩니다. 모의와 스텁을 구별하기가 어려울 수 있기 때문에 이것을 추가하지만이 예제는 두 가지를 함께 사용하는 방법을 명확하게 보여줍니다.
user3344977

훌륭한 설명, 감사합니다. API 변경에 대한 질문을 약간 수정했습니다. API가 아니므로 개발 프로세스에 참여하지 않으면 어떻게 되나요? 클라이언트 라이브러리가 언제 실패하는지 알고 싶습니다.
ThinkDigital

@ThinkDigital 훌륭한 API 제공 업체는 출시 노트가 양호하고 변경 사항을 올바르게 전달합니다. 해당 채널이없는 경우 회의에 앉아 논의 할 시간이 될 수 있습니다. 훌륭한 개발자는 항상 새 버전의 API 변경을 조사하고 API 버전을 업그레이드하지 않아도됩니다. API 버전이 있습니까? 그 중 어느 것도 그것을 잡지 못하면 QAing을 통해 알게 될 것입니다. 팀 전체의 테스트 ← 의무를 업데이트하십시오. → 단일 개발자의 의무 : 크게 신경 쓰지 않아야합니다. 서버가 오류를 반환하거나 서버가 오류를 반환하지 않지만 json을 구문 분석 할 수없는 경우를 처리하거나 올바른 경우를 처리하십시오.
Honey

@Honey 님, 답변 주셔서 감사합니다! 필자의 경우 API가있는 pub.dev 클라이언트를 유지하고 있지만 심각하게 부족합니다. 공식 API를 사용하는 것보다 사이트를 스크랩하여 API를 만드는 것이 낫습니다. 이로 인해 사이트를 변경하면 코드가 손상 될 수 있으며이 경우 다른 사람을 업데이트하지 않아도됩니다. 사이트는 오픈 소스이지만 좀 더 사소한 변경 사항을 기반으로하는 API를 유지 관리하는 것은 다릅니다.
ThinkDigital

32

SO에 대한 많은 답변과 웹에 조롱에 관한 좋은 게시물이 있습니다. Martin Fowler Mocks Are n't Stubs 가 조롱에 대한 많은 아이디어를 논의하는 게시물을 살펴보십시오 .

한 단락에서-Mocking은 의존성에 의존하지 않고 코드 단위를 테스트 할 수있는 특정 기법입니다. 일반적으로 조롱을 다른 방법과 차별화하는 것은 코드 종속성을 대체하는 데 사용되는 모의 객체가 기대치를 설정할 수 있다는 것입니다. 모의 객체는 코드에 의해 호출되는 방법과 응답 방법을 알 수 있습니다.


귀하의 원래 질문에 TypeMock이 언급되었으므로 아래에 그 대답을 남겼습니다.

TypeMock은 상용 조롱 프레임 워크 의 이름입니다 .

RhinoMocks 및 Moq와 같은 무료 조롱 프레임 워크의 모든 기능과 더 강력한 옵션을 제공합니다.

TypeMock이 필요한지 여부는 논란의 여지가 없습니다. 무료 모의 라이브러리를 사용하여 원하는 대부분의 조롱을 수행 할 수 있으며 많은 사람들이 TypeMock이 제공하는 기능으로 인해 캡슐화 된 디자인에서 벗어날 수 있다고 주장합니다.

또 다른 대답에서 언급 한 것처럼 'TypeMocking'은 실제로 정의 된 개념이 아니지만 CLR 프로파일 러를 사용하여 런타임에 .Net 호출을 가로 채기 위해 TypeMock이 제공하는 조롱 유형을 의미하여 객체를 위조 할 수있는 훨씬 큰 기능을 제공 할 수 있습니다 (요구 사항 아님) 인터페이스 또는 가상 메소드 필요).


@Masoud는 TypeMock을 언급하지 않았습니다. 그의 질문은 일반적으로 "타입 조롱"에 관한 것이었다.
Peter Lillevold

4
@Peter-다른 의견이 말했듯이 질문의 편집 기록을 확인하십시오. 답변을 게시하면 원래 질문이 완전히 변경되면 할 수있는 일이 많지 않습니다.
David Hall

9

Mock은 실제 방법 / 개체의 동작을 제어 된 방식으로 시뮬레이션하는 방법 / 개체입니다. 모의 객체는 단위 테스트에 사용됩니다.

테스트중인 메소드는 종종 다른 외부 서비스 또는 메소드 내의 다른 메소드를 호출합니다. 이를 종속성이라고합니다. 조롱 한 종속성은 정의한 방식으로 작동합니다.

모의에 의해 의존성을 제어함으로써, 우리는 코딩 한 메소드의 동작을 쉽게 테스트 할 수 있습니다. 이것은 단위 테스트입니다.

모의 객체의 목적은 무엇입니까?

Mocks vs 스텁

단위 테스트와 기능 테스트


7

Mocking은 테스트를위한 실제 객체 동작을 시뮬레이션하는 의사 객체를 생성합니다.


5

모의 유형의 목적은 테스트를 특정 단위로 분리하기 위해 종속성을 분리하는 것입니다. 스텁은 단순한 대리자이며 모의자는 사용법을 확인할 수있는 대리자입니다. 모의 프레임 워크는 스텁 및 모의 생성을 도와주는 도구입니다.

편집 : 원래 문구 언급 "type mocking"이후 나는 이것이 TypeMock과 관련이 있다는 인상을 받았습니다. 내 경험상 일반적인 용어는 "모의"입니다. TypeMock에 대한 아래 정보를 무시하십시오.

TypeMock Isolator는 수정 IL을 즉석에서 작동한다는 점에서 대부분의 다른 조롱 프레임 워크와 다릅니다. 따라서 대부분의 다른 프레임 워크가 조롱 할 수없는 유형과 인스턴스를 조롱 할 수 있습니다. 이러한 유형 / 인스턴스를 다른 프레임 워크와 조롱하려면 고유 한 추상화를 제공하고 조롱해야합니다.

TypeMock은 깨끗한 런타임 환경을 희생하면서 뛰어난 유연성을 제공합니다. TypeMock이 결과를 얻는 방식의 부작용으로 때로는 TypeMock을 사용할 때 매우 이상한 결과를 얻을 수 있습니다.


@Masoud는 TypeMock을 언급하지 않았습니다. 그의 질문은 일반적으로 "타입 조롱"에 관한 것이었다.
Peter Lillevold

1
@Peter : 원래의 표현은 "타입 조롱이란 무엇입니까?"였습니다.
Brian Rasmussen

알아. "type mocking"은 "TypeMock"과 동일하지 않으므로 귀하와 @Oded 답변이 모두 마크에서 벗어난 것을 발견했습니다.
Peter Lillevold

1
@ 피터 : 내 경험상 일반적인 용어는 "모의"이지만 어쨌든 나는 분명히 대답하기 위해 내 대답을 업데이트했습니다. 입력 해 주셔서 감사합니다.
Brian Rasmussen

3

TypeMock 아이솔레이터 조롱 프레임 워크를 사용하면 TypeMocking이 될 것이라고 생각합니다.

IoC를 염두에두고 코드를 작성할 필요없이 단위 테스트에 사용할 모의 객체를 생성하는 도구입니다.


@Masoud는 TypeMock을 언급하지 않았습니다. 그의 질문은 일반적으로 "타입 조롱"에 관한 것이었다.
Peter Lillevold

3
실제로, 원래의 질문에는 "Mocking"앞에 "Type"이라는 단어가 포함되었지만 나중에 편집되었습니다. 그렇기 때문에 일부 답변에 TypeMock에 대한 특정 정보가 포함되어 있습니다.
Martin Liversage

1

모의에 네트워크 요청이 포함 된 경우 다른 대안은 실제 테스트 서버를 사용하는 것입니다. 이 서비스를 사용하여 테스트 요청 및 응답을 생성 할 수 있습니다. http://testerurl.com/


방금 액세스를 시도했지만 몇 분이 걸렸습니다. 누가 비밀리에 요청을 기록하지 않는다고 말합니까? 마지막으로, 이것은 코멘트로 더 나을 수 있습니다 :)
Kieren Johnstone

무료 호스팅으로 옮기고 싶지 않아서 실제로 중단했습니다. 그렇습니다, 이것은 주석이었을 것입니다. 오픈 소스이므로 요청 로깅에 대한 우려가있는 경우 직접 실행할 수 있습니다. github.com/captainchung/TesterUrl
Matthew Chung
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.