File: new_instances_test.rb

package info (click to toggle)
ruby-flexmock 3.0.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 836 kB
  • sloc: ruby: 7,572; makefile: 6
file content (231 lines) | stat: -rw-r--r-- 6,154 bytes parent folder | download | duplicates (3)
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
#!/usr/bin/env ruby

#---
# Copyright 2003-2013 by Jim Weirich (jim.weirich@gmail.com).
# All rights reserved.

# Permission is granted for use, copying, modification, distribution,
# and distribution of modified versions of this work as long as the
# above copyright notice is included.
#+++

require 'test_helper'

class TestNewInstances < Minitest::Test
  include FlexMock::Minitest
  include FlexMock::RedirectError

  class Dog
    def bark
      :woof
    end
    def wag
      :tail
    end
    def self.make
      new
    end
  end

  class Cat
    attr_reader :name
    def initialize(name, &block)
      @name = name
      block.call(self) if block_given?
    end
  end

  class Connection
    def initialize(*args)
      yield(self) if block_given?
    end
    def send(args)
      post(args)
    end
    def post(args)
      :unstubbed
    end
  end

  def test_new_instances_allows_stubbing_of_existing_methods
    flexstub(Dog).new_instances do |obj|
      obj.should_receive(:bark).and_return(:whimper)
    end
    m = Dog.new
    assert_equal :whimper,  m.bark
  end

  def test_new_instances_is_transparent_after_flexmock_teardown
    flexstub(Dog).new_instances.should_receive(:bark).never
    flexmock_teardown
    Dog.new
  end

  def test_new_instances_before_and_after_flexmock_teardown_are_disconnected
    flexstub(Dog).new_instances.should_receive(:bark).never
    flexmock_teardown
    flexstub(Dog).new_instances.should_receive(:bark).once
    Dog.new.bark
  end

  def test_new_instances_stubs_still_have_existing_methods
    flexstub(Dog).new_instances do |obj|
      obj.should_receive(:bark).and_return(:whimper)
    end
    m = Dog.new
    assert_equal :tail,  m.wag
  end

  def test_new_instances_mock_methods_called_in_initialize
    klass = Class.new do
      attr_reader :value
      def initialize; @value = bark end
      def bark; :original end
    end
    flexmock(klass).new_instances do |obj|
      obj.should_receive(:bark).and_return(:mock)
    end
    obj = klass.new
    assert_equal :mock, obj.value
  end

  def test_new_instances_will_pass_args_to_new
    flexstub(Cat).new_instances do |obj|
      obj.should_receive(:meow).and_return(:scratch)
    end
    x = :not_called
    m = Cat.new("Fido") { x = :called }
    assert_equal :scratch,  m.meow
    assert_equal "Fido", m.name
    assert_equal :called, x
  end

  # Some versions of the software had problems invoking the block after a
  # second stubbing.
  def test_new_gets_block_after_restubbing
    flexstub(Cat).new_instances { }
    x = :not_called
    m = Cat.new("Fido") { x = :called }
    assert_equal :called, x
    flexmock_teardown

    flexstub(Cat).new_instances { }
    x = :not_called
    m = Cat.new("Fido") { x = :called }
    assert_equal :called, x
  end

  def test_new_instances_stub_verification_happens_on_teardown
    flexstub(Dog).new_instances do |obj|
      obj.should_receive(:bark).once.and_return(nil)
    end

    Dog.new
    ex = assert_raises(assertion_failed_error) { flexmock_teardown }
    assert_match(/method 'bark\(.*\)' called incorrect number of times/i, ex.message)
  end

  def test_new_instances_reports_error_on_non_classes
    ex = assert_raises(ArgumentError) {
      flexstub(Dog.new).new_instances do |obj|
        obj.should_receive(:hi)
      end
    }
    assert_match(/Class/, ex.message)
    assert_match(/new_instances/, ex.message)
  end

  def test_does_not_by_default_stub_objects_created_with_allocate
    flexstub(Dog).new_instances do |obj|
      obj.should_receive(:bark).and_return(:whimper)
    end
    m = Dog.allocate
    assert_equal :woof,  m.bark
  end

  def test_can_explicitly_stub_objects_created_with_allocate
    flexstub(Dog).new_instances(:allocate) do |obj|
      obj.should_receive(:bark).and_return(:whimper)
    end
    m = Dog.allocate
    assert_equal :whimper,  m.bark
  end

  def test_can_stub_objects_created_with_arbitrary_class_methods
    flexstub(Dog).new_instances(:make) do |obj|
      obj.should_receive(:bark).and_return(:whimper)
    end
    assert_equal :whimper,  Dog.make.bark
  end

  def test_stubbing_arbitrary_class_methods_leaves_new_alone
    flexstub(Dog).new_instances(:make) do |obj|
      obj.should_receive(:bark).and_return(:whimper)
    end
    assert_equal :woof,  Dog.new.bark
  end

  def test_stubbing_new_and_allocate_doesnt_double_stub_objects_on_new
    counter = 0
    flexstub(Dog).new_instances do |obj|
      counter += 1
    end
    Dog.new
    assert_equal 1, counter
  end

  # Current behavior does not install stubs into the block passed to new.
  # This is rather difficult to achieve, although it would be nice.  For the
  # moment, we assure that they are not stubbed, but I am willing to change
  # this in the future.
  def test_blocks_on_new_do_not_have_stubs_installed
    flexstub(Connection).new_instances do |new_con|
      new_con.should_receive(:post).and_return {
        :stubbed
      }
    end
    block_run = false
    Connection.new do |c|
      assert_equal :stubbed, c.send("hi")
      block_run = true
    end
    assert block_run
  end

  def test_new_instances_accept_chained_expectations
    flexmock(Dog).new_instances.
      should_receive(:growl).and_return(:grr).
      should_receive(:roll_over).and_return(:flip)
    assert_equal :grr, Dog.new.growl
    assert_equal :flip, Dog.new.roll_over
  end

  def test_fancy_use_of_chained_should_received
    flexmock(Dog).new_instances.should_receive(:woof => :grrr)
    assert_equal :grrr, Dog.new.woof
  end

  def test_writable_accessors
    flexmock(Dog).new_instances.should_receive(:name=).with("fido")
    dog = Dog.new
    dog.name = 'fido'
  end

  def test_ordering_can_be_specified
    dog = Dog.new
    flexmock(dog).should_receive(:bark).once.ordered
    flexmock(dog).should_receive(:bite).once.ordered
    dog.bark
    dog.bite
  end

  def test_ordering_can_be_specified_in_groups
    dog = Dog.new
    flexmock(dog).should_receive(:wag).once.ordered(:safe)
    flexmock(dog).should_receive(:bark).once.ordered(:danger)
    flexmock(dog).should_receive(:bite).once.ordered(:danger)
    dog.wag
    dog.bite
    dog.bark
  end
end