File: stub_implementation_spec.rb

package info (click to toggle)
ruby-rspec 3.13.0c0e0m0s1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 6,856 kB
  • sloc: ruby: 70,868; sh: 1,423; makefile: 99
file content (112 lines) | stat: -rw-r--r-- 3,960 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
module RSpec
  module Mocks
    RSpec.describe "stub implementation" do
      describe "with no args" do
        it "execs the block when called" do
          obj = double
          allow(obj).to receive(:foo) { :bar }
          expect(obj.foo).to eq :bar
        end
      end

      describe "with one arg" do
        it "execs the block with that arg when called" do
          obj = double
          allow(obj).to receive(:foo) { |given| given }
          expect(obj.foo(:bar)).to eq :bar
        end
      end

      describe "with variable args" do
        it "execs the block when called" do
          obj = double
          allow(obj).to receive(:foo) { |*given| given.first }
          expect(obj.foo(:bar)).to eq :bar
        end
      end
    end

    RSpec.describe "unstubbing with `and_call_original`" do
      it "replaces the stubbed method with the original method" do
        obj = Object.new
        def obj.foo; :original; end
        allow(obj).to receive(:foo)
        allow(obj).to receive(:foo).and_call_original
        expect(obj.foo).to eq :original
      end

      it "removes all stubs with the supplied method name" do
        obj = Object.new
        def obj.foo; :original; end
        allow(obj).to receive(:foo).with(1)
        allow(obj).to receive(:foo).with(2)
        allow(obj).to receive(:foo).and_call_original
        expect(obj.foo).to eq :original
      end

      it "does not remove any expectations with the same method name" do
        obj = Object.new
        def obj.foo; :original; end
        expect(obj).to receive(:foo).with(3).and_return(:three)
        allow(obj).to receive(:foo).with(1)
        allow(obj).to receive(:foo).with(2)
        allow(obj).to receive(:foo).and_call_original
        expect(obj.foo(3)).to eq :three
      end

      shared_examples_for "stubbing `new` on class objects" do
        it "restores the correct implementations when stubbed and unstubbed on a parent and child class" do
          parent = stub_const("Parent", Class.new)
          child  = stub_const("Child", Class.new(parent))

          allow(parent).to receive(:new)
          allow(child).to receive(:new)
          allow(parent).to receive(:new).and_call_original
          allow(child).to receive(:new).and_call_original

          expect(parent.new).to be_an_instance_of parent
          expect(child.new).to be_an_instance_of child
        end

        it "restores the correct implementations when stubbed and unstubbed on a grandparent and grandchild class" do
          grandparent = stub_const("GrandParent", Class.new)
          parent      = stub_const("Parent", Class.new(grandparent))
          child       = stub_const("Child", Class.new(parent))

          allow(grandparent).to receive(:new)
          allow(child).to receive(:new)
          allow(grandparent).to receive(:new).and_call_original
          allow(child).to receive(:new).and_call_original

          expect(grandparent.new).to be_an_instance_of grandparent
          expect(child.new).to be_an_instance_of child
        end
      end

      context "when partial doubles are not verified" do
        before { expect(RSpec::Mocks.configuration.verify_partial_doubles?).to be false }
        include_examples "stubbing `new` on class objects"
      end

      context "when partial doubles are verified" do
        include_context "with isolated configuration"
        before { RSpec::Mocks.configuration.verify_partial_doubles = true }
        include_examples "stubbing `new` on class objects"

        if RSpec::Support::RubyFeatures.required_kw_args_supported?
          binding.eval(<<-RUBY, __FILE__, __LINE__)
          it "handles keyword arguments correctly" do
            klass = Class.new do
              def initialize(kw:)
              end
            end

            allow(klass).to receive(:new).and_call_original
            klass.new(kw: 42)
          end
          RUBY
        end
      end
    end
  end
end