How do I stub things in MiniTest? How do I stub things in MiniTest? ruby ruby

How do I stub things in MiniTest?


  # Create a mock object  book = MiniTest::Mock.new  # Set the mock to expect :title, return "War and Piece"  # (note that unless we call book.verify, minitest will  # not check that :title was called)  book.expect :title, "War and Piece"  # Stub Book.new to return the mock object  # (only within the scope of the block)  Book.stub :new, book do    wp = Book.new # returns the mock object    wp.title      # => "War and Piece"  end


I use minitest for all my Gems testing, but do all my stubs with mocha, it might be possible to do all in minitest with Mocks(there is no stubs or anything else, but mocks are pretty powerful), but I find mocha does a great job, if it helps:

require 'mocha'    Books.any_instance.stubs(:title).returns("War and Peace")


If you're interesting in simple stubbing without a mocking library, then it's easy enough to do this in Ruby:

class Book  def avg_word_count_per_page    arr = word_counts_per_page    sum = arr.inject(0) { |s,n| s += n }    len = arr.size    sum.to_f / len  end  def word_counts_per_page    # ... perhaps this is super time-consuming ...  endenddescribe Book do  describe '#avg_word_count_per_page' do    it "returns the right thing" do      book = Book.new      # a stub is just a redefinition of the method, nothing more      def book.word_counts_per_page; [1, 3, 5, 4, 8]; end      book.avg_word_count_per_page.must_equal 4.2    end  endend

If you want something more complicated like stubbing all instances of a class, then it is also easy enough to do, you just have to get a little creative:

class Book  def self.find_all_short_and_unread    repo = BookRepository.new    repo.find_all_short_and_unread  endenddescribe Book do  describe '.find_all_short_unread' do    before do      # exploit Ruby's constant lookup mechanism      # when BookRepository is referenced in Book.find_all_short_and_unread      # then this class will be used instead of the real BookRepository      Book.send(:const_set, BookRepository, fake_book_repository_class)    end    after do      # clean up after ourselves so future tests will not be affected      Book.send(:remove_const, :BookRepository)    end    let(:fake_book_repository_class) do      Class.new(BookRepository)    end    it "returns the right thing" do       # Stub #initialize instead of .new so we have access to the      # BookRepository instance      fake_book_repository_class.send(:define_method, :initialize) do        super        def self.find_all_short_and_unread; [:book1, :book2]; end      end      Book.find_all_short_and_unread.must_equal [:book1, :book2]    end  endend