SusSourceSusReceive

class Receive

Represents an expectation that a method will be called on an object.

Nested

Definitions

def initialize(base, method, &block)

Initialize a new Receive expectation.

Signature

parameter base Object

The base object (usually self from Base).

parameter method Symbol

The method name to expect.

yields {...}

Optional block that returns the value to return from the method.

Implementation

def initialize(base, method, &block)
	@base = base
	@method = method
	
	@times = Times.new
	@arguments = nil
	@options = nil
	@block = nil
	
	@returning = block
end

def print(output)

Print a representation of this expectation.

Signature

parameter output Output

The output target.

Implementation

def print(output)
	output.write("receive ", :variable, @method.to_s, :reset)
end

def with_arguments(predicate)

Specify that the method should be called with specific arguments.

Signature

parameter predicate Object

The predicate to match against the arguments.

returns Receive

Returns self for method chaining.

Implementation

def with_arguments(predicate)
	@arguments = WithArguments.new(predicate)
	return self
end

def with_options(predicate)

Specify that the method should be called with specific keyword options.

Signature

parameter predicate Object

The predicate to match against the options.

returns Receive

Returns self for method chaining.

Implementation

def with_options(predicate)
	@options = WithOptions.new(predicate)
	return self
end

def with_block(predicate = Be.new(:!=, nil))

Specify that the method should be called with a block.

Signature

parameter predicate Object

Optional predicate to match against the block.

returns Receive

Returns self for method chaining.

Implementation

def with_block(predicate = Be.new(:!=, nil))
	@block = WithBlock.new(predicate)
	return self
end

def with(*arguments, **options)

Specify that the method should be called with specific arguments and options.

Signature

parameter arguments Array

The positional arguments to match.

parameter options Hash

The keyword arguments to match.

returns Receive

Returns self for method chaining.

Implementation

def with(*arguments, **options)
	with_arguments(Be.new(:==, arguments)) if arguments.any?
	with_options(Be.new(:==, options)) if options.any?
	return self
end

def once

Specify that the method should be called exactly once.

Signature

returns Receive

Returns self for method chaining.

Implementation

def once
	@times = Times.new(Be.new(:==, 1))
	return self
end

def twice

Specify that the method should be called exactly twice.

Signature

returns Receive

Returns self for method chaining.

Implementation

def twice
	@times = Times.new(Be.new(:==, 2))
	return self
end

def with_call_count(predicate)

Specify a predicate to match against the call count.

Signature

parameter predicate Object

The predicate to match against the call count.

returns Receive

Returns self for method chaining.

Implementation

def with_call_count(predicate)
	@times = Times.new(predicate)
	return self
end

def and_return(*returning, &block)

Specify the value to return when the method is called.

Signature

parameter returning Array

Values to return. If one value, returns it directly; if multiple, returns an array.

yields {...}

Optional block that computes the return value.

returns Receive

Returns self for method chaining.

raises ArgumentError

If both values and a block are provided.

Implementation

def and_return(*returning, &block)
	if block_given?
		if returning.any?
			raise ArgumentError, "Cannot specify both a block and returning values."
		end
		
		@returning = block
	elsif returning.size == 1
		@returning = proc{returning.first}
	else
		@returning = proc{returning}
	end
	
	return self
end

def and_raise(...)

Specify that the method should raise an exception when called.

Signature

parameter exception Class, String

The exception class or message to raise.

returns Receive

Returns self for method chaining.

Implementation

def and_raise(...)
	@returning = proc do
		raise(...)
	end
	
	return self
end

def validate(mock, assertions, arguments, options, block)

Validate the method call arguments, options, and block.

Signature

parameter mock Mock

The mock instance.

parameter assertions Assertions

The assertions instance.

parameter arguments Array

The positional arguments.

parameter options Hash

The keyword arguments.

parameter block Proc, nil

The block argument.

Implementation

def validate(mock, assertions, arguments, options, block)
	return unless @arguments or @options or @block
	
	assertions.nested(self) do |assertions|
		@arguments.call(assertions, arguments) if @arguments
		@options.call(assertions, options) if @options
		@block.call(assertions, block) if @block
	end
end

def call(assertions, subject)

Evaluate this expectation against a subject.

Signature

parameter assertions Assertions

The assertions instance to use.

parameter subject Object

The object to expect the method call on.

Implementation

def call(assertions, subject)
	assertions.nested(self) do |assertions|
		mock = @base.mock(subject)
		
		called = 0
		
		if call_original?
			mock.before(@method) do |*arguments, **options, &block|
				called += 1
				
				validate(mock, assertions, arguments, options, block)
			end
		else
			mock.replace(@method) do |*arguments, **options, &block|
				called += 1
				
				validate(mock, assertions, arguments, options, block)
				
				next @returning.call(*arguments, **options, &block)
			end
		end
		
		if @times
			assertions.defer do
				@times.call(assertions, called)
			end
		end
	end
end

def call_original?

Signature

returns Boolean

Whether the original method should be called.

Implementation

def call_original?
	@returning.nil?
end