File: expected_arg_verification_spec.rb

package info (click to toggle)
ruby-rspec 3.5.0c3e0m0s0-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 6,312 kB
  • ctags: 4,788
  • sloc: ruby: 62,572; sh: 785; makefile: 100
file content (128 lines) | stat: -rw-r--r-- 4,996 bytes parent folder | download | duplicates (4)
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
require 'support/doubled_classes'

module RSpec
  module Mocks
    RSpec.describe 'Expected argument verification (when `#with` is called)' do
      # Note: these specs here aren't meant to be exhaustive. The specs in
      # rspec-support for the method signature verifier are. Here we are just
      # covering the code paths within the `with` implementation, including
      # the special handling for `any_args` and `no_args`.
      context "when doubling an unloaded class" do
        it 'allows any arguments' do
          expect(defined?(UnloadedClass)).to be_falsey
          inst_dbl = instance_double("UnloadedClass")

          expect {
            expect(inst_dbl).to receive(:message).with(:foo, :bar, :bazz)
          }.not_to raise_error

          reset inst_dbl
        end
      end

      context "when doubling a loaded class" do
        let(:dbl) { instance_double(LoadedClass) }
        after { reset dbl }

        context "when `any_args` is used" do
          context "as the only argument" do
            it "is allowed regardless of how many args the method requires" do
              expect {
                expect(dbl).to receive(:instance_method_with_two_args).with(any_args)
              }.not_to raise_error
            end
          end

          context "as the first argument, with too many additional args" do
            it "is disallowed" do
              expect {
                expect(dbl).to receive(:instance_method_with_two_args).with(any_args, 1, 2, 3)
              }.to fail_with("Wrong number of arguments. Expected 2, got 3.")
            end
          end

          context "as the first argument, with an allowed number of additional args" do
            it "is allowed" do
              expect {
                expect(dbl).to receive(:instance_method_with_two_args).with(any_args, 1, 2)
              }.not_to raise_error

              expect {
                expect(dbl).to receive(:instance_method_with_two_args).with(any_args, 1)
              }.not_to raise_error
            end
          end
        end

        context "when `no_args` is used" do
          it "allows a method expectation on a method that accepts no arguments" do
            expect(LoadedClass.instance_method(:defined_instance_method).arity).to eq(0)

            expect {
              expect(dbl).to receive(:defined_instance_method).with(no_args)
            }.not_to raise_error
          end

          it "allows a method expectation on a method that has defaults for all arguments" do
            expect {
              expect(dbl).to receive(:instance_method_with_only_defaults).with(no_args)
            }.not_to raise_error
          end

          it "does not allow a method expectation on a method that has required arguments" do
            expect {
              expect(dbl).to receive(:instance_method_with_two_args).with(no_args)
            }.to fail_with("Wrong number of arguments. Expected 2, got 0.")
          end

          if RSpec::Support::RubyFeatures.required_kw_args_supported?
            context "for a method with required keyword args" do
              it 'covers the required args when `any_args` is last' do
                expect {
                  expect(dbl).to receive(:kw_args_method).with(1, any_args)
                }.not_to raise_error
              end

              it 'does not cover the required args when there are args after `any_args`' do
                expect {
                  # Use eval to avoid syntax error on 1.8 and 1.9
                  eval("expect(dbl).to receive(:kw_args_method).with(any_args, optional_arg: 3)")
                }.to fail_with("Missing required keyword arguments: required_arg")
              end
            end
          end
        end

        if RSpec::Support::RubyFeatures.required_kw_args_supported?
          it 'does not cover required args when `any_args` is not used' do
            expect {
              expect(dbl).to receive(:kw_args_method).with(anything)
            }.to fail_with("Missing required keyword arguments: required_arg")
          end
        end

        context "when a list of args is provided" do
          it "allows a method expectation when the arity matches" do
            expect {
              expect(dbl).to receive(:instance_method_with_two_args).with(1, 2)
            }.not_to raise_error
          end

          it "does not allow a method expectation with an arity mismatch" do
            expect {
              expect(dbl).to receive(:instance_method_with_two_args).with(1, 2, 3)
            }.to fail_with("Wrong number of arguments. Expected 2, got 3.")
          end
        end

        context "when `with` is called with no args" do
          it "fails with an error suggesting the user use `no_args` instead" do
            expect {
              expect(dbl).to receive(:instance_method_with_two_args).with
            }.to raise_error(ArgumentError, /no_args/)
          end
        end
      end
    end
  end
end