rspec-process-mocks 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -81,6 +81,90 @@ Feature: expect a message
81
81
  And the output should contain "expected: 1 time"
82
82
  And the output should contain "received: 0 times"
83
83
 
84
+ Scenario: expect a message, and it is called twice
85
+ Given a file named "spec/account_spec.rb" with:
86
+ """
87
+ RSpec.configuration.mock_framework = :rspec
88
+ $: << File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'lib'))
89
+ require 'rspec/process_mocks'
90
+ require "account"
91
+
92
+ describe Account do
93
+ context "when closed" do
94
+ it "logs an account closed message in a child process" do
95
+
96
+ logger = double("logger")
97
+ account = Account.new
98
+ account.logger = logger
99
+
100
+ logger.should_receive_in_child_process(:account_closed)
101
+
102
+ account.close
103
+
104
+ sleep 0.1
105
+ end
106
+ end
107
+ end
108
+ """
109
+ And a file named "lib/account.rb" with:
110
+ """
111
+ class Account
112
+ attr_accessor :logger
113
+
114
+ def close
115
+ Process.fork do
116
+ logger.account_closed
117
+ logger.account_closed
118
+ end
119
+ end
120
+ end
121
+ """
122
+ When I run `rspec spec/account_spec.rb`
123
+ Then the output should contain "1 example, 1 failure"
124
+ And the output should contain "expected: 1 time"
125
+ And the output should contain "received: 2 times"
126
+
127
+ Scenario: expect a message at least once, and it is called twice
128
+ Given a file named "spec/account_spec.rb" with:
129
+ """
130
+ RSpec.configuration.mock_framework = :rspec
131
+ $: << File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'lib'))
132
+ require 'rspec/process_mocks'
133
+ require "account"
134
+
135
+ describe Account do
136
+ context "when closed" do
137
+ it "logs an account closed message in a child process" do
138
+
139
+ logger = double("logger")
140
+ account = Account.new
141
+ account.logger = logger
142
+
143
+ logger.should_receive_in_child_process(:account_closed).at_least(1).times
144
+
145
+ account.close
146
+
147
+ sleep 0.1
148
+ end
149
+ end
150
+ end
151
+ """
152
+ And a file named "lib/account.rb" with:
153
+ """
154
+ class Account
155
+ attr_accessor :logger
156
+
157
+ def close
158
+ Process.fork do
159
+ logger.account_closed
160
+ logger.account_closed
161
+ end
162
+ end
163
+ end
164
+ """
165
+ When I run `rspec spec/account_spec.rb`
166
+ Then the output should contain "1 example, 0 failure"
167
+
84
168
  @wip
85
169
  Scenario: expect a message with an argument
86
170
  Given a file named "spec/account_spec.rb" with:
@@ -6,60 +6,67 @@ module RSpec
6
6
  def initialize(*args)
7
7
  super
8
8
 
9
- # The tempfile is used for interprocess communication
10
- @tempfile = Tempfile.new("should-receive-#{@expected_from.object_id}-#{@sym}")
9
+ # The temp files are used for interprocess communication.
10
+ # This one stores the calls that are exact matches.
11
+ @actual_tempfile = Tempfile.new("should-receive-#{@expected_from.object_id}-#{@sym}")
12
+ # This one stores the similar calls.
13
+ @similar_tempfile = Tempfile.new("should-receive-similar-#{@expected_from.object_id}-#{@sym}")
11
14
  end
12
- def verify_messages_received
13
- # Maybe we should add a sleep loop here if @tempfile is empty. This may
14
- # prevent a user of this library from having to add a sleep in the spec.
15
- # Maybe this:
16
- # @tempfile.rewind
17
- # lines = @tempfile.readlines
18
- # timeout = Configure.verify_timeout
19
- # while lines.empty? && timeout > 0
20
- # sleep 0.1
21
- # timeout -= 0.1
22
- # @tempfile.rewind
23
- # lines = @tempfile.readlines
24
- # end
25
15
 
26
- @tempfile.rewind
27
- lines = @tempfile.readlines
28
- #puts "lines in verify_messages_received: #{lines.inspect}"
29
- return true if lines.size == 1 #&& # Called exactly once.
30
- # lines[0] == "[]\n" # Called with no arguments.
31
16
 
32
- generate_error
33
- rescue RSpec::Mocks::MockExpectationError => error
34
- error.backtrace.insert(0, @expected_from)
35
- Kernel::raise error
17
+ # This method is executed in the _child_ process when the stubbed method
18
+ # is called exact arguments
19
+ # Overwritten from rspec.
20
+ def invoke(*args, &block)
21
+ msg = args.inspect
22
+ @actual_tempfile.puts msg
23
+ @actual_tempfile.flush
36
24
  end
37
25
 
38
- # This is a hack to get it to work. But it means we can only ever expect
39
- # exactly 1 message.
40
- def matches_exact_count?
41
- lines.size == 1
26
+ # This method is executed in the _child_ process when the stubbed method
27
+ # is called with similar argument.
28
+ # Overwritten from rspec.
29
+ def advise(*args)
30
+ @similar_tempfile.puts msg
31
+ @similar_tempfile.flush
32
+ similar_messages
42
33
  end
43
34
 
44
- # This method is executed in the _child_ process when the stubbed method
45
- # is called.
46
- def invoke(*args, &block)
35
+ # This overwrites the rspec implementation because we need to record
36
+ # similar messages in a temp file not instance variables.
37
+ def similar_messages
38
+ @similar_tempfile.rewind
39
+ @similar_tempfile.readlines
40
+ end
47
41
 
48
- msg = args.inspect
49
- @tempfile.puts msg
50
- @tempfile.flush
51
- # puts "##{@sym} called on #{@expected_from.class}-#{@expected_from.object_id}; args: #{args.inspect}"
52
- # yield block, *args if defined?(block)
42
+ # Reads back the actual/exact-match arguments written to the temp file.
43
+ # This is not a method in rspec.
44
+ def actual_messages
45
+ @actual_tempfile.rewind
46
+ @actual_tempfile.readlines
53
47
  end
54
48
 
55
- # This is a hack to get it to work. But it means we don't get info about
56
- # "similar" methods in the failure output. Similar messages are those with
57
- # a matching method name, but not matching arguments.
58
- # Note: this is only a rough definition of "similar" methods. "Similar"
59
- # methods are not part of RSpec's external API, so their definition is not
60
- # strictly documented.
61
- def similar_messages
62
- []
49
+ # The following methods used to use instance variables. But we can't do
50
+ # that because those aren't shared between processes. These methods
51
+ # overwrite rspec's behavior and instead keep the state in temp files.
52
+ def actual_received_count
53
+ actual_messages.size
54
+ end
55
+ def generate_error
56
+ if similar_messages.empty?
57
+ @error_generator.raise_expectation_error(@sym, @expected_received_count, actual_received_count, *@args_expectation.args)
58
+ else
59
+ @error_generator.raise_similar_message_args_error(self, *similar_messages)
60
+ end
61
+ end
62
+ def matches_at_least_count?
63
+ @at_least && actual_received_count >= @expected_received_count
64
+ end
65
+ def matches_at_most_count?
66
+ @at_most && actual_received_count <= @expected_received_count
67
+ end
68
+ def matches_exact_count?
69
+ @expected_received_count == actual_received_count
63
70
  end
64
71
  end
65
72
  end
@@ -1,7 +1,7 @@
1
1
  module RSpec # :nodoc:
2
2
  module ProcessMocks # :nodoc:
3
3
  module Version # :nodoc:
4
- STRING = '0.0.1'
4
+ STRING = '0.0.2'
5
5
  end
6
6
  end
7
7
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: rspec-process-mocks
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.1
5
+ version: 0.0.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Paul Cortens
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-05-28 00:00:00 -07:00
13
+ date: 2011-06-08 00:00:00 -07:00
14
14
  default_executable:
15
15
  dependencies: []
16
16
 
@@ -64,6 +64,6 @@ rubyforge_project:
64
64
  rubygems_version: 1.5.0
65
65
  signing_key:
66
66
  specification_version: 3
67
- summary: rspec-process-mocks-0.0.1
67
+ summary: rspec-process-mocks-0.0.2
68
68
  test_files: []
69
69