How do I stub things in MiniTest?

前端 未结 8 921
面向向阳花
面向向阳花 2020-12-02 09:46

Within my test I want to stub a canned response for any instance of a class.

It might look like something like:

Book.stubs(:title).any_instance().ret         


        
8条回答
  •  天涯浪人
    2020-12-02 10:25

    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 ...
      end
    end
    
    describe 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
      end
    end
    

    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
      end
    end
    
    describe 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
      end
    end
    

提交回复
热议问题