File: spies.feature

package info (click to toggle)
ruby-rspec 3.9.0c2e2m1s3-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 6,612 kB
  • sloc: ruby: 67,456; sh: 1,572; makefile: 98
file content (131 lines) | stat: -rw-r--r-- 5,821 bytes parent folder | download | duplicates (2)
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
129
130
131
Feature: Spies

  [Message expectations](./expecting-messages) put an example's expectation at the start, before you've invoked the
  code-under-test. Many developers prefer using an arrange-act-assert (or given-when-then)
  pattern for structuring tests. Spies are an alternate type of test double that support this
  pattern by allowing you to expect that a message has been received after the fact, using
  `have_received`.

  You can use any test double (or partial double) as a spy, but the double must be setup to
  spy on the messages you care about. Spies automatically spy on all messages,
  or you can [allow a message](./allowing-messages) to spy on it.

  `have_received` supports the same fluent interface for [setting constraints](../setting-constraints) that normal message expectations do.

  Note: The `have_received` API shown here will only work if you are using rspec-expectations.
  Note: `have_received(...).with(...)` is unable to work properly when passed arguments are mutated after the spy records the received message.

  Scenario: Using a spy
    Given a file named "spy_spec.rb" with:
      """ruby
      RSpec.describe "have_received" do
        it "passes when the message has been received" do
          invitation = spy('invitation')
          invitation.deliver
          expect(invitation).to have_received(:deliver)
        end
      end
      """
    When I run `rspec spy_spec.rb`
    Then the examples should all pass

  Scenario: Spy on a method on a partial double
    Given a file named "partial_double_spy_spec.rb" with:
      """ruby
      class Invitation
        def self.deliver; end
      end

      RSpec.describe "have_received" do
        it "passes when the expectation is met" do
          allow(Invitation).to receive(:deliver)
          Invitation.deliver
          expect(Invitation).to have_received(:deliver)
        end
      end
      """
    When I run `rspec partial_double_spy_spec.rb`
    Then the examples should all pass

  Scenario: Failure when the message has not been received
    Given a file named "failure_spec.rb" with:
      """ruby
      class Invitation
        def self.deliver; end
      end

      RSpec.describe "failure when the message has not been received" do
        example "for a spy" do
          invitation = spy('invitation')
          expect(invitation).to have_received(:deliver)
        end

        example "for a partial double" do
          allow(Invitation).to receive(:deliver)
          expect(Invitation).to have_received(:deliver)
        end
      end
      """
     When I run `rspec failure_spec.rb --order defined`
     Then it should fail with:
      """
        1) failure when the message has not been received for a spy
           Failure/Error: expect(invitation).to have_received(:deliver)

             (Double "invitation").deliver(*(any args))
                 expected: 1 time with any arguments
                 received: 0 times with any arguments
      """
      And it should fail with:
      """
        2) failure when the message has not been received for a partial double
           Failure/Error: expect(Invitation).to have_received(:deliver)

             (Invitation (class)).deliver(*(any args))
                 expected: 1 time with any arguments
                 received: 0 times with any arguments
      """

  Scenario: Set constraints using the fluent interface
    Given a file named "setting_constraints_spec.rb" with:
      """ruby
      RSpec.describe "An invitiation" do
        let(:invitation) { spy("invitation") }

        before do
          invitation.deliver("foo@example.com")
          invitation.deliver("bar@example.com")
        end

        it "passes when a count constraint is satisfied" do
          expect(invitation).to have_received(:deliver).twice
        end

        it "passes when an order constraint is satisifed" do
          expect(invitation).to have_received(:deliver).with("foo@example.com").ordered
          expect(invitation).to have_received(:deliver).with("bar@example.com").ordered
        end

        it "fails when a count constraint is not satisfied" do
          expect(invitation).to have_received(:deliver).at_least(3).times
        end

        it "fails when an order constraint is not satisifed" do
          expect(invitation).to have_received(:deliver).with("bar@example.com").ordered
          expect(invitation).to have_received(:deliver).with("foo@example.com").ordered
        end
      end
      """
    When I run `rspec setting_constraints_spec.rb --order defined`
    Then it should fail with the following output:
      | 4 examples, 2 failures                                                                              |
      |                                                                                                     |
      |  1) An invitiation fails when a count constraint is not satisfied                                   |
      |     Failure/Error: expect(invitation).to have_received(:deliver).at_least(3).times                  |
      |       (Double "invitation").deliver(*(any args))                                                    |
      |           expected: at least 3 times with any arguments                                             |
      |           received: 2 times with any arguments                                                      |
      |                                                                                                     |
      |  2) An invitiation fails when an order constraint is not satisifed                                  |
      |     Failure/Error: expect(invitation).to have_received(:deliver).with("foo@example.com").ordered    |
      |       #<Double "invitation"> received :deliver out of order                                         |