Stubs

Stubs Stubbing은 테스트에서 사용되는 기법으로, 실제 객체나 아직 구현되지 않은 코드를 대신하여 미리 정의된 응답을 제공하는 메커니즘 목적 의존성 격리: 실제 구현체로부터 테스트 대상을 분리하여 독립적인 테스트를 가능하게 합니다. 특정 시나리오 테스트: 다양한 상황에 대한 테스트를 용이하게 합니다. 미구현 코드 대체: 아직 개발되지 않은 부분을 임시로 대체할 수 있습니다. 테스트 속도 향상: 실제 리소스 접근 없이 빠른 테스트가 가능합니다. 특징 미리 정의된 응답(canned answer)을 제공합니다. 실제 코드의 동작을 단순화하여 모사합니다. 주로 상태 테스팅에 중점을 둡니다. 메서드 호출의 결과만 정의하며, 호출 여부는 검증하지 않습니다. 사용 사례 구현되지 않은 함수나 외부 라이브러리 함수를 사용할 때 복잡한 로직을 단순화하여 테스트하고자 할 때 특정 조건에서의 예외 상황을 테스트할 때 외부 의존성(예: 데이터베이스, 네트워크 요청)을 가진 코드를 테스트할 때 예시 Python 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 from unittest.mock import Mock, patch import pytest from datetime import datetime # 테스트할 실제 클래스 class PaymentService: def __init__(self, payment_gateway): self.payment_gateway = payment_gateway def process_payment(self, amount): if amount <= 0: raise ValueError("Amount must be positive") response = self.payment_gateway.charge(amount) if response['status'] == 'success': return True return False # 외부 결제 게이트웨이 클래스 (실제로는 외부 서비스) class PaymentGateway: def charge(self, amount): # 실제로는 외부 API를 호출하는 복잡한 로직 pass # Stub 예시 class PaymentGatewayStub: def charge(self, amount): # 항상 성공 응답을 반환하는 단순한 구현 return {'status': 'success', 'timestamp': datetime.now()} # 테스트 코드 def test_payment_service_with_stub(): # Stub 사용 gateway_stub = PaymentGatewayStub() payment_service = PaymentService(gateway_stub) assert payment_service.process_payment(100) == True Javascript 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 // Jest를 사용한 테스트 예시 const { jest } = require('@jest/globals'); // 테스트할 실제 클래스 class UserService { constructor(database) { this.database = database; } async getUserById(id) { const user = await this.database.findUser(id); if (!user) { throw new Error('User not found'); } return user; } async updateUserEmail(id, newEmail) { const user = await this.database.findUser(id); if (!user) { throw new Error('User not found'); } user.email = newEmail; await this.database.updateUser(id, user); return user; } } // Stub 예시 class DatabaseStub { constructor() { this.users = new Map([ [1, { id: 1, name: 'John Doe', email: 'john@example.com' }], [2, { id: 2, name: 'Jane Doe', email: 'jane@example.com' }] ]); } async findUser(id) { return this.users.get(id); } async updateUser(id, userData) { this.users.set(id, userData); return userData; } } // 테스트 코드 describe('UserService', () => { // Stub을 사용한 테스트 describe('with stub', () => { const dbStub = new DatabaseStub(); const userService = new UserService(dbStub); test('should return user when exists', async () => { const user = await userService.getUserById(1); expect(user.name).toBe('John Doe'); }); test('should throw error when user not found', async () => { await expect(userService.getUserById(999)) .rejects .toThrow('User not found'); }); }); }); 참고 및 출처

November 1, 2024 · 3 min · Me