Module: Brown::TestHelpers

Included in:
Agent
Defined in:
lib/brown/test.rb

Overview

Additional testing methods for Agent.

You can cause these methods to become part of Agent with

require 'brown/test'

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object

:nodoc:



12
13
14
15
16
17
18
19
# File 'lib/brown/test.rb', line 12

def self.included(base)
	base.class_eval do
		%i{memo amqp_publisher amqp_listener}.each do |m|
			alias_method "#{m}_without_test".to_sym, m
			alias_method m, "#{m}_with_test".to_sym
		end
	end
end

Instance Method Details

#amqp_listener?(exchange_name) ⇒ Boolean

Is there a listener on the specified exchange name registered on this agent?

Parameters:

  • exchange_name (#to_s)

Returns:

  • (Boolean)

    Boolean



145
146
147
# File 'lib/brown/test.rb', line 145

def amqp_listener?(exchange_name)
	@amqp_listeners && @amqp_listeners[exchange_name.to_s].is_a?(Proc)
end

#amqp_listener_with_test(exchange_name, *args, &blk) ⇒ Object

:nodoc:

Test-specific decorator to record the details of a listener.



125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/brown/test.rb', line 125

def amqp_listener_with_test(exchange_name, *args, &blk)
	@amqp_listeners ||= {}

	if exchange_name.is_a? Array
		exchange_name.each do |en|
			@amqp_listeners[en.to_s] = blk
		end
	else
		@amqp_listeners[exchange_name.to_s] = blk
	end

	amqp_listener_without_test(exchange_name, *args, &blk)
end

#amqp_publisher?(name) ⇒ Boolean

Is there a publisher with the specified name registered on this agent?

Parameters:

  • name (Symbol)

Returns:

  • (Boolean)

    Boolean



117
118
119
# File 'lib/brown/test.rb', line 117

def amqp_publisher?(name)
	@amqp_publishers && @amqp_publishers[name]
end

#amqp_publisher_with_test(name, *args) ⇒ Object

:nodoc:

Test-specific decorator to record the existence of a publisher.



103
104
105
106
107
108
109
# File 'lib/brown/test.rb', line 103

def amqp_publisher_with_test(name, *args)
	@amqp_publishers ||= {}

	@amqp_publishers[name] = true

	amqp_publisher_without_test(name, *args)
end

#amqp_receive(exchange_name, payload, **opts) ⇒ Boolean

Cause a message to be received by the listener on exchange_name.

Parameters:

  • exchange_name (#to_s)

    the name of the exchange.

  • payload (String)

    the literal string which is the payload of the message.

Returns:

  • (Boolean)

    whether or not the message was acked. You usually want to check that this is true, because an agent that doesn't ack each message when it has finished processing it is almost always buggy, but there are specialised circumstances where you actually want to not ack the message.

Raises:

  • (ArgumentError)

    if you attempt to send a message via an exchange that isn't being listened on.



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/brown/test.rb', line 165

def amqp_receive(exchange_name, payload, **opts)
	unless amqp_listener?(exchange_name)
		raise ArgumentError,
		      "Unknown exchange: #{exchange_name}"
	end

	msg = Brown::Agent::AMQPMessageMock.new(opts.merge(payload: payload))

	self.new.tap do |p|
		uuid = SecureRandom.uuid
		p.singleton_class.__send__(:define_method, uuid, &@amqp_listeners[exchange_name])
		p.__send__(uuid, msg)
	end

	msg.acked?
end

#memo?(name) ⇒ Boolean

Is there a memo with the specified name registered on this agent?

Parameters:

  • name (Symbol)

Returns:

  • (Boolean)

    Boolean



38
39
40
# File 'lib/brown/test.rb', line 38

def memo?(name)
	@memos && @memos.has_key?(name)
end

#memo_with_test(name, safe = false, &generator) ⇒ Object

:nodoc:

Test-specific decorator to replace the "real" memo container object with a test-enabled alternative.



47
48
49
50
51
52
# File 'lib/brown/test.rb', line 47

def memo_with_test(name, safe=false, &generator)
	memo_without_test(name, safe, &generator)

	# Throw out the real memo, replace with our own testing-enabled variant
	@memos[name] = Brown::Agent::Memo.new(generator, safe, true)
end

#reset_memosObject

Reset all memos to "undefined" values.

Because memo values are cached at the class level, this means that they're cached between test cases. Often, this isn't what you want (because if the value of the memo was changed by a test case, the next test won't run in a pristine environment). Calling this method will cause all of the memos in the agent to be reset to a state which is the same as if the memo had never been called at all.



63
64
65
66
67
68
69
# File 'lib/brown/test.rb', line 63

def reset_memos
	@memos ||= {}

	@memos.values.each do |memo|
		memo.instance_variable_set(:@cached_value, nil)
	end
end

#stimulus?(name) ⇒ Boolean

Is there not an arbitrary stimulus with the specified name registered on this agent?

Parameters:

  • name (Symbol)

Returns:

  • (Boolean)

    Boolean



28
29
30
# File 'lib/brown/test.rb', line 28

def stimulus?(name)
	@stimuli && @stimuli.has_key?(name)
end

#timer?(n) ⇒ Boolean

Is there a timer which will go off every n seconds registered on this agent?

Parameters:

  • n (Integer)

Returns:

  • (Boolean)

    Boolean



78
79
80
# File 'lib/brown/test.rb', line 78

def timer?(n)
	!instance_methods.select { |m| m =~ /^every_#{n}__/ }.empty?
end

#trigger(n) ⇒ Object

Set off all timers which trigger every n seconds on the running agent.

Parameters:

  • n (Integer)


86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/brown/test.rb', line 86

def trigger(n)
	trigger_methods = self.instance_methods.select { |m| m =~ /^every_#{n}__/ }

	if trigger_methods.empty?
		raise RuntimeError,
		      "Nothing is set to run every #{n} second#{n == 1 ? "" : "s"}"
	end

	trigger_methods.each do |m|
		self.new.__send__(m)
	end
end