0
0

More than 1 year has passed since last update.

#Ruby #Rspec mock method chain ( is it correct way ? )

Last updated at Posted at 2020-04-24
class User
  def initialize(name:, age: )
    @name = name
    @age = age
  end

  attr_reader :name, :age

  def book
    Book.new(author: name)
  end

  def book_number
    book.number
  end
end

class Book
  def initialize(author: nil)
    @author = author
    @number = Random.rand(999_999)
  end

  attr_reader :author, :number
end

require "rspec"

describe do
  context "No mock" do
    subject { user.book_number }

    let(:user) { User.new(name: "Alice", age: 20) }

    it do
      is_expected.to be_a Integer

      expect(user.name).to eq "Alice"
      expect(user.age).to eq 20
    end
  end

  context "NG mock" do
    subject { user.book_number }

    let(:user) { User.new(name: "Alice", age: 20) }

    it do
      # NoMethodError:
      # undefined method `number' for nil:NilClass
      allow(user).to receive(:book)

      is_expected.to be_a Integer

      expect(user.name).to eq "Alice"
      expect(user.age).to eq 20
    end
  end

  context "OK allow mock" do
    subject { user.book_number }

    let(:user) { User.new(name: "Alice", age: 20) }

    it do
      allow(user).to receive(:book).and_return Book.new

      is_expected.to be_a Integer

      expect(user.name).to eq "Alice"
      expect(user.age).to eq 20
    end
  end

  context "OK expect mock" do
    subject { user.book_number }

    let(:user) { User.new(name: "Alice", age: 20) }

    it do
      expect(user).to receive(:book).and_return Book.new

      is_expected.to be_a Integer

      expect(user.name).to eq "Alice"
      expect(user.age).to eq 20
    end
  end

  context "NG expect mock (method chain)" do
    subject { user.book_number }

    let(:user) { User.new(name: "Alice", age: 20) }

    it do
      # Failure/Error: expect(user.book).to receive(:number)
      #
      # (#<Book:0x00007fd5468f4aa8 @author="Alice", @number=415630>).number(*(any args))
      #     expected: 1 time with any arguments
      #     received: 0 times with any arguments
      expect(user.book).to receive(:number)

      is_expected.to be_a Integer
    end
  end

  context "OK expect mock (method chain)" do
    subject { user.book_number }

    let(:user) { User.new(name: "Alice", age: 20) }

    it do
      allow(user).to receive(:book).and_return Book.new
      expect(user.book).to receive(:number).and_call_original

      is_expected.to be_a Integer
    end
  end
end

Original by Github issue

チャットメンバー募集

何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

Twitter

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0