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")