Mock

28 April 2014

Mock 객체

  • 모듈의 겉모양이 실제 모듈과 비슷하게 보이도록 만든 가짜 객체.
  • 실제 객체를 만들기엔 비용과 시간이 많이 들거나, 의존성이 길게 걸쳐져 있어 구현이 어려울 경우 이런 가짜 객체를 만들어 사용한다.
  • 테스트 작성을 위한 환경 구축이 어려울 때 사용
  • 환경 구축을 위한 작업 시간이 많이 필요할 때. DB, 서버, FTP 등을 설치해야만 테스트가 가능해질 때.
  • 특정 모듈을 아직 가지고 있지 않아서 테스트 환경을 구축하지 못할 때.
  • 타 부서와의 협의나 정책이 필요할 때.
  • 테스트가 특정 경우나 순간에 의존적일 때 사용
  • 특정한 경우나 순간이 항상 재현될 수 있도록 Mock을 사용한다.
  • 테스트 시간이 오래 걸릴 때 사용
  • 개인 PC, 서버의 성능 문제로 인해 오래 걸릴 수도 있지만, 특정 모듈을 호출했을 때 멀리 갔다 오느라 시간이 오래 걸리는 경우. 기능 수행 그 자체보다 테스트 수행 시 영향을 미치는 다른 부분으로 인해 오래 걸리는 경우 Mock을 사용한다.

Test Double

  • 대역, 스턴트맨을 나타내는 Stunt Double 이라는 단어에서 차용해온 단어로, 오리지널 객체를 사용해서 테스트를 진행하기가 어려울 경우 이를 대신하여 테스트를 진행할 수 있도록 만들어주는 객체를 지칭.
  • 다섯개의 하위 분류로 나뉜다.

Dummy Object

  • 말 그대로 멍청한 모조품, 단순한 껍데기. 오로지 인스턴스화 될 수 있는 수준으로만 구현된 객체.
  • 단지 인스턴스화된 객체가 필요할 뿐 해당 객체의 기능까지는 필요하지 않은 경우 사용. 따라서 해당 더미 객체의 메소드가 호출됬을 때의 정상 동작은 보장되지 않는다.

Test Stub

  • Dummy Object가 마치 실제로 동작하는 것처럼 보이게 만들어놓은 객체. 객체의 특정 상태를 가정해서 만들어놓은 단순 구현체.
  • 미리 지정(하드코딩)된 특정한 값을 리턴해주거나 특정 메시지를 출력하는 등의 작업을 한다.

Fake Object

  • 복잡한 로직이나 객체 내부에서 필요로 하는 다른 외부 객체들의 동작을 비교적 단순화하여 구현한 객체. 테스트 케이스 작성을 진행하기 위해 필요한 다른 객체들과의 의존성을 제거하기 위해 사용된다.
  • Stub이 한 개의 인스턴스를 대표하는데 주로 쓰인다면, Fake Object는 여러 개의 인스턴스를 대표하거나, 좀 더 복잡한 구현이 들어가 있는 객체를 지칭한다.

Dummy Object: 단지 인스턴스화 될 수 있는 객체 수준

Test Stub: 인스턴스화 된 객체가 ‘특정 상태나 모습’을 대표함.

Fake Object: 여러 개의 인스턴스를 대표하거나, 좀 더 복잡한 구현이 들어가 있음.

Test Spy

  • 특정 메소드의 정상 호출 여부를 확인해야 할 때 사용한다.
  • Dummy, Stub, Fake를 포함한 Test Double로 구현된 객체 전 범위에 걸쳐 Spy 기능을 추가할 수 있다.
  • 예를 들어 Student 클래스의 getName() 메소드가 몇 번이나 호출되었는지 테스트를 하고 싶을 때, MockStudent 클래스에 count라는 멤버 변수를 추가한다. 그리고 getName() 메소드에서 count를 증가시키도록 한다. 마지막으로 MockStudent 인스턴스의 사용이 끝났을 때, count 값을 확인하는 방식으로 테스트한다. (물론 Mock 프레임워크를 사용하면 이런 작업이 필요 없다.)

Mock Object

  • Mock 객체는 상태(state)가 아닌 행위(behavior)를 검증하기 위해 사용되는 객체를 지칭한다. 대부분 Mock 프레임워크를 사용한다.
  • 일반적인 Test Double은 상태(state)를 기반으로 테스트 케이스를 작성한다. 반면 Mock 객체는 행위(behavior)를 기반으로 테스트 케이스를 작성한다.

참고) 여기서 말한 Mock Object라는 용어는 Double의 다섯가지 분류 중 한 가지로 소개된 것이다. 그러나 일반적으로 사용되는 Mock ObjectTest Double과 동일한 의미, 즉 행위 기반 테스트에 한정된 것이 아닌 더 넓은 개념으로 사용되니 혼동하지 않아야 한다.

다섯가지 분류를 설명할 때가 아닌 이상 Mock ObjectTest Double과 같이 넓은 의미로 이해하면 된다.

Mock Framework

동적으로 Mock 객체를 만들어주는 프레임워크를 지칭. Mock 객체를 직접 명시적인 클래스로 만들지 않아도 되며, 상태 뿐 아니라 행위까지도 테스트 케이스에 포함시킬 수 있다. 대표적으로 EasyMock, jMock, Mockito 등이 있다.

Mockito

EashMock, jMock의 단점을 보완하는 Mock 프레임워크.

  1. CreateMock: 인터페이스에 해당하는 Mock 객체를 만든다.
  2. Stub: 테스트에 필요한 Mock 객체의 동작을 지정한다.
  3. Exercise: 테스트 메소드 내에서 Mock 객체를 사용한다.
  4. Verify: 메소드가 예상대로 호출되었는지 검증한다.

// TO DO.. 아직 정리를 못함

given, when, then

Mockito 개발자가 자신의 블로그에 테스트 케이스 작성을 위한 궁극의 템플릿이라며 호들갑스럽게(ㅋㅋ) 밝힌 템플릿. BDD 스타일을 따르며, 의미적으로 각 단계를 구분함으로써 가독성이 높아진다.

public void testSomething() throws Exception{
	//given : 선행 조건 기술

	//when : 기능 수행

	//then : 결과 확인
}

References

TDD (Test Driven Development) Adapter 패턴 (Wrapper 패턴)