1. Background
특정 클래스에 have_received 와 함께 사용하도록 최적화된 테스트 더블을 생성함. 주어진 클래스명이 로드되어 있으면, 해당 클래스에 정의된 인스턴스 메서드만 스텁할 수 있다.
일반적으로 double을 사용할 때는 스파이를 사용하려면 먼저 메서드를 스텁했어야 하나, instance_spy는 클래스가 응답하는 모든 인스턴스 메서드를 자동으로 스파이합니다.
2. Usage
RSpec.describe Component::Powerlevel10kComponent do
subject(:p10k) { described_class.new }
let(:mock_git) { instance_spy(Component::GitComponent) }
let(:mock_ohmyzsh) { instance_spy(Component::OhMyZshComponent) }
let(:null_logger) { Logger.new(File::NULL) }
# ...
describe '#install' do
context 'when already installed' do
it 'does nothing' do
allow(p10k).to receive(:installed?).and_return(true)
p10k.install
expect(mock_git).not_to have_received(:clone)
end
end
3. Reference
4. Jargon
- stub
- 테스트 중 어떤 객체나 더블에 대해 "이 메서드를 호출하면 미리 정해둔 값을 반환하라" 라고 지시하는 기법
- RSpec에서는 allow(object).to receive(:method_name).and_return(value) 형태로 사용
- 내부 로직을 대체하거나 외부 의존성을 격리할 때 활용
- Test Double
- Martin Fowler 가 소개한 개념
- 실제 객체(real object)를 대신(fake)해 테스트에 활용하는 모든 객체를 포함
5. Chatgpt Answers
Ruby·RSpec에서의 구현
double: 이름만 있는 가벼운 더블. 모든 메서드를 stub으로 사전 정의해야 함.ruby
복사편집
user = double("User", name: "Alice") allow(user).to receive(:admin?).and_return(true)instance_double(klass): 로드된 클래스klass의 인스턴스 메서드만 허용(컴파일 타임 안전성↑).spy/instance_spy: 메서드를 호출하면서 동시에 스파이 기능(호출 기록)을 제공.ruby
복사편집
logger = spy("Logger") logger.info("hello") expect(logger).to have_received(:info).with("hello")