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

Test Doubles

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

Test Doubles

Avatar for Stephanie Viccari

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