테스트코드(Test Code)

Mock 객체란?

Junuuu 2022. 3. 15. 18:56
728x90

Mock 객체란?

Mock은 사전적 의미로 모조품이라는 뜻을 가집니다.

즉, 제품의 외양을 흉내 낸 모조품을 말하며 소프트웨어에서는 모듈의 겉모양이 실제 모듈과 비슷하게 보이도록 만든 가짜 객체를 Mock 객체라고 합니다.

 

왜 사용할까요?

테스트 카이스 작성이 어려운 상황과 Mock 객체가 필요한 상황은 종종 일치하곤 합니다.

대부분의 경우 모듈이 가진 '의존성'이 근본적인 원인이 됩니다.

따라서 그 '의존성'을 단절시키기 위해 사용합니다.

 

예를 들어 다음과 같은 상황에 사용합니다.

 

1. 테스트 작성을 위한 환경 구축이 어려울 때

  • 다른 부서와 연계 모듈이어서 다른 쪽에서 승인을 해줘야 테스트가 가능한 경우
  • 방화벽으로 막혀 있어서 통과가 어려운 경우
  • 다른 부서에게 모듈을 아직 넘겨받디 못한 경우
  • 오라클 데이터베이스를 설치해야 테스트가 가능한 경우
  • 웹 서버, 웹 애플리케이션 서버, FTP 서버 등을 설치해야만 테스트가 가능한 경우

2. 테스트가 특정 경우나 순간에 의존적이여서

  • 네트워크의 접속 시간제한을 구현하려고 하는데 접속 시도 후 5초까지 1초마다 접속을 재시도하고 그 이후에는 연결 실패 메시지를 띄우려고 하는데 4초, 즉 네 번째 재시도에 접속이 되는 경우를 테스트로 만드는 경우

3. 테스트 시간이 오래 걸릴 때

  • 개인 PC의 성능이나 서버의 성능 문제로 인해 오래 걸릴 수도 있지만 특정한 모듈을 호출했을 때 시간이 오래 걸리는 구간이나 모듈을 Mock으로 대체해서 만듭니다.

 

어떻게 사용할까요?

사용자 암호 저장 기능에 대한 테스트 케이스를 작성한다고 생각하여 보겠습니다.

@Test
public void savePasswordTest() throws Exception{
	UserRegister register = new UserRegister();
    
	String userId = "sweet88";
	String password = "potato";
	
	register.savePassword(userId, password);
	assertEquals(password, register.getPassword(userId));

}

TDD의 정석대로 다음과 같은 테스트 코드를 구현해 보았습니다.

 

만약 다음과 같은 요구사항이 추가로 존재하면 어떻게 될까요?

 

패스워드는 반드시 암호화한 다음에 저장해라

 

암호화 모듈의 인터페이스는 다음과 같이 정해져 있습니다.

public interface Cipher {
	public String encrypt(String source);
	public String decrypt(String source);
}

 

이때 암호화 모듈은 다음 팀에서 제공합니다.

이제 암호화 부분은 제외하고 테스트 케이스를 작성해 보겠습니다.

@Test
public void savePasswordTest() throws Exception{
	UserRegister register = new UserRegister();
	Chipher cipher = ???? // 옆 팀에서 만들어줘야함...
    
	String userId = "sweet88";
	String password = "potato";
	
	register.savePassword(userId, cipher.encrypt(password));
	String decryptedPassword = cipher.decrypt(register.getPassword(userId));
	assertEquals(password, decryptedPassword);

}

테스트 메서드는 다 만들었지만 암호화 클래스를 옆 팀에서 제공해주지 않아 실행은커녕 컴파일조차 못하고 있습니다.

사실 개발자 입장에서 암호화 기능은 관심 밖입니다.

따라서 암호화 클래스처럼 보이는 Mock 객체를 만들어서 개발에 사용하면 됩니다.

 

인터페이스가 존재하므로 해당 인터페이스를 구현하는 Mock 클래스를 만듭니다.

 

https://repo.yona.io/files/4000

암호화할 대상인 문자열 'potato'의 해시 문자열을 다음과 같이 찾았습니다.

 

이제 Mock 객체를 만들어 보겠습니다.

public class MockCipher implements Cipher {

	@Override
	public String decrypt(String source){
		return "potato";
	}

	@Override
	public String encrypt(String source){
		return "8ee2027983915ec78acc45027d874316";
	}

}

 

테스트 코드를 완성해 보겠습니다

@Test
public void savePasswordTest() throws Exception{
	UserRegister register = new UserRegister();
	Chipher cipher = new MockCipher();
    
	String userId = "sweet88";
	String password = "potato";
	
	register.savePassword(userId, cipher.encrypt(password));
	String decryptedPassword = cipher.decrypt(register.getPassword(userId));
	assertEquals(password, decryptedPassword);

}

 

 

 

 

출처

https://repo.yona.io/files/4000

https://repo.yona.io/doortts/blog/issue/1

 

"TDD 실천법과 도구" 책 전체를 PDF 공개합니다.

2010년 6월에 출간되었던 "TDD 실천법과 도구" 책 전체를 PDF로 공개합니다. 책소개: http://naver.me/GaYZCDjD Updated --- - [1장 - 테스트주도개발 Test Driven Development](https://repo.yona.io/doortts/blog/issue/2) - 18.07.18 -

repo.yona.io

https://site.mockito.org/

 

Mockito framework site

Intro Why How More Who Links Training Why drink it? Mockito is a mocking framework that tastes really good. It lets you write beautiful tests with a clean & simple API. Mockito doesn’t give you hangover because the tests are very readable and they produc

site.mockito.org