Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Test Doubles

Test Doubles

Stephanie Viccari

January 05, 2021
Tweet

More Decks by Stephanie Viccari

Other Decks in Education

Transcript

  1. Using a double RSpec.describe "Book" do describe "#title" do it

    "stands in for a real object" do book_double = double("book", title: "Whale Sounds, Volume I") book_double.title expect(book_double.title).to eq("Whale Sounds, Volume I") end end end 3
  2. Calling an unknown method RSpec.describe "Book" do describe "#title" do

    it "stands in for a real object" do book_double = double("book", title: "Whale Sounds, Volume I") book_double.method_that_does_not_exist # => <Double "book’> received unexpected message :method_that_does_not_exist end end end 4
  3. Instance doubles class Book def title end end RSpec.describe "Book"

    do describe "#title" do it "stands in for a real object" do invalid_book_double = instance_double("Book", description: "") # => the Book class does not implement the instance method: description end end end 5
  4. Let's Compare double • creates an object that stands in

    place of another object • can define methods on the test object • ex: double("book", title: "") 6
  5. Let's Compare instance_double • ensures the defined methods match the

    real object in our system • ex: instance_double(Book, title: "") • ex: instance_double("Book", title: "") 7
  6. Using a Test Double to Focus our Test class Book

    def self.from_amazon(asin:) book = AmazonBookFinder.run(asin) new(book: book) end delegate :title, to: :@book private_class_method :new def initialize(book:) @book = book end end 10
  7. Using a Test Double to Focus our Test RSpec.describe BestSellerTitle

    do describe "#title" do it "prepends title with 'best seller'" do book = Book.from_amazon($amazon_whale_songs_book_asin) title = BestSellerTitle.new(book).title expect(title).to eq("Best Seller: Whale Songs") end end end 11
  8. Using a Test Double to Focus our Test RSpec.describe BestSellerTitle

    do describe "#title" do it "prepends title with 'best seller'" do book_double = instance_double(Book, title: "Whale Songs") title = BestSellerTitle.new(book_double).title expect(title).to eq("Best Seller: Whale Songs") end end end 12
  9. Testing a books controller RSpec.describe BooksController do describe "#index" do

    it "returns 10 published books" do books = FactoryBot.create_list(:book, 10, published: true) FactoryBot.create(:book, published: false) get :index expect(assigns[:books]).to match_array(books) end end end 13
  10. 14

  11. allowing behavior Let's stub the latest_published scope on Book. books

    = FactoryBot.build_stubbed_list(:book, 3) allow(Book).to receive(:latest_published).and_return(books) 16
  12. Stubbing our Book class RSpec.describe BooksController do describe "#index" do

    it "returns 10 published books" do books = FactoryBot.build_stubbed_list(:book, 3) allow(Book).to receive(:latest_published).and_return(books) get :index expect(assigns[:books]).to eq(books) end end end 17
  13. RSpec.describe BooksController do describe "#index" do it "returns 10 published

    books" do books = FactoryBot.build_stubbed_list(:book, 3) allow(Book).to receive(:latest_published).and_return(books) get :index expect(assigns[:books]).to eq(books) end end end 18
  14. RSpec.describe BooksController do describe "#index" do it "returns 10 published

    books" do books = FactoryBot.build_stubbed_list(:book, 3) allow(Book).to receive(:latest_published).and_return(books) get :index expect(assigns[:books]).to eq(books) end end end 19
  15. RSpec.describe BooksController do describe "#index" do it "returns 10 published

    books" do books = FactoryBot.build_stubbed_list(:book, 3) allow(Book).to receive(:latest_published).and_return(books) get :index expect(assigns[:books]).to eq(books) end end end 20
  16. RSpec.describe BooksController do describe "#index" do it "returns 10 published

    books" do books = FactoryBot.build_stubbed_list(:book, 3) allow(Book).to receive(:latest_published).and_return(books) get :index expect(assigns[:books]).to eq(books) end end end 21
  17. 24

  18. Testing arguments # books_controller.rb Book.limit(per_page) # books_controller_spec.rb RSpec.describe BooksController do

    describe "#index" do it "finds the 10 latest published books" do books = FactoryBot.build_list(:book, 10) allow(Book).to receive(:limit).and_return(books) get :index expect(assigns[:books]).to eq(books) end end end 25
  19. Testing arguments # books_controller.rb Book.limit(per_page) # books_controller_spec.rb RSpec.describe BooksController do

    describe "#index" do it "finds the 10 latest published books" do books = FactoryBot.build_list(:book, 10) allow(Book).to receive(:limit).with(10).and_return(books) get :index expect(assigns[:books]).to eq(books) end end end 26
  20. Query methods Ask a question • What is the user's

    name? • array.empty? • string.length • user.email 28
  21. Command methods Have side effects • Update the user's email!

    • user.save! • array.push • book.update_attributes 29
  22. Stubbing query methods describe Signup do context "email" do it

    "delegates to the user" do user_double = instance_double("User", email: "[email protected]") signup = Signup.new(user: user_double) expect(signup.email).to eq(user.email) end end end 30
  23. Stubbing command methods describe Signup do context "#complete" do it

    "verifies the user's account" do user = instance_double("User") allow(user).to receive(:verify) signup = Signup.new(user: user) signup.complete(email: "[email protected]") end end end 31
  24. Stubbing command methods describe Signup do context "#complete" do it

    "calls verify on the user" do user = instance_double("User") allow(user).to receive(:verify) signup = Signup.new(user: user) signup.complete(email: "[email protected]") end end end 32
  25. Stubbing command methods describe Signup do context "#complete" do it

    "calls verify on the user" do user = instance_double("User") expect(user).to receive(:verify).with(email: "[email protected]") signup = Signup.new(user: user) signup.complete(email: "[email protected]") end end end 33
  26. Stubbing command methods describe Signup do context "#complete" do it

    "calls verify on the user" do user = instance_double("User") expect(user).to receive(:verify).with(email: "[email protected]") signup = Signup.new(user: user) signup.complete(email: "[email protected]") end end end 34
  27. Stubbing command methods describe Signup do context "#complete" do it

    "calls verify on the user" do user = instance_double("User") expect(user).to receive(:verify).with(email: "[email protected]") signup = Signup.new(user: user) signup.complete(email: "[email protected]") end end end 35
  28. Stubbing command methods describe Signup do context "#complete" do it

    "calls verify on the user" do user = instance_double("User") expect(user).to receive(:verify).with(email: "[email protected]") signup = Signup.new(user: user) signup.complete(email: "[email protected]") end end end 36
  29. Stubbing command methods describe Signup do context "#complete" do it

    "calls verify on the user" do user = instance_double("User") expect(user).to receive(:verify).with(email: "[email protected]") signup = Signup.new(user: user) signup.complete(email: "[email protected]") end end end 37
  30. Order please! describe Signup do context "#complete" do it "calls

    verify on the user" do # Setup user = instance_double("User") signup = Signup.new(user: user) # Setup and also verification??? expect(user).to receive(:verify).with(email: [email protected]) # Exercise signup.complete(email: "[email protected]") end end end 38
  31. Stubbing command methods describe Signup do context "#complete" do it

    "calls verify on the user" do # Setup user = instance_double("User") allow(user).to receive(:verify) signup = Signup.new(user: user) # Exercise signup.complete(email: "[email protected]") # Verify expect(user).to have_received(:verify).with(email: [email protected]) end end end 39
  32. Stubbing command methods describe Signup do context "#complete" do it

    "calls verify on the user" do # Setup user = instance_double("User") allow(user).to receive(:verify) signup = Signup.new(user: user) # Exercise signup.complete(email: "[email protected]") # Verify expect(user).to have_received(:verify).with(email: [email protected]) end end end 40
  33. Stubbing command methods describe Signup do context "#complete" do it

    "calls verify on the user" do # Setup user = instance_double("User") allow(user).to receive(:verify) signup = Signup.new(user: user) # Exercise signup.complete(email: "[email protected]") # Verify expect(user).to have_received(:verify).with(email: [email protected]) end end end 41
  34. Stubbing command methods describe Signup do context "#complete" do it

    "calls verify on the user" do # Setup user = instance_double("User") allow(user).to receive(:verify) signup = Signup.new(user: user) # Exercise signup.complete(email: "[email protected]") # Verify expect(user).to have_received(:verify).with(email: [email protected]) end end end 42
  35. Resources RSpec Mocks - https://relishapp.com/rspec/rspec- mocks/v/3-10/docs/basics Stubs, Mocks, Spies, and

    Fakes - https://thoughtbot.com/upcase/videos/ stubs-mocks-spies-and-fakes The Bike Shed: Hollywood-themed tour of RSpec mocks, stubs, and spies - https://www.bikeshed.fm/270 43