class FlexMock::SignatureValidator

Validate that the call matches a given signature

The validator created by {#initialize} matches any method call

Attributes

optional_arguments[R]

The number of optional arguments

optional_keyword_arguments[R]

The names of optional keyword arguments @return [Set<Symbol>]

required_arguments[R]

The number of required arguments

required_keyword_arguments[R]

The names of required keyword arguments @return [Set<Symbol>]

Public Class Methods

from_instance_method(exp, instance_method) click to toggle source

Create a validator that represents the signature of an existing method

# File lib/flexmock/validators.rb, line 245
def self.from_instance_method(exp, instance_method)
  required_arguments, optional_arguments, splat = 0, 0, false
  required_keyword_arguments, optional_keyword_arguments, keyword_splat = Set.new, Set.new, false
  instance_method.parameters.each do |type, name|
    case type
    when :req then required_arguments += 1
    when :opt then optional_arguments += 1
    when :rest then splat = true
    when :keyreq then required_keyword_arguments << name
    when :key then optional_keyword_arguments << name
    when :keyrest then keyword_splat = true
    when :block
    else raise ArgumentError, "cannot interpret parameter type #{type}"
    end
  end
  new(exp,
      required_arguments: required_arguments,
      optional_arguments: optional_arguments,
      splat: splat,
      required_keyword_arguments: required_keyword_arguments,
      optional_keyword_arguments: optional_keyword_arguments,
      keyword_splat: keyword_splat)
end
new( expectation, required_arguments: 0, optional_arguments: 0, splat: true, required_keyword_arguments: [], optional_keyword_arguments: [], keyword_splat: true) click to toggle source
# File lib/flexmock/validators.rb, line 177
def initialize(
    expectation,
    required_arguments: 0,
    optional_arguments: 0,
    splat: true,
    required_keyword_arguments: [],
    optional_keyword_arguments: [],
    keyword_splat: true)
  @exp = expectation
  @required_arguments = required_arguments
  @optional_arguments = optional_arguments
  @required_keyword_arguments = required_keyword_arguments.to_set
  @optional_keyword_arguments = optional_keyword_arguments.to_set
  @splat = splat
  @keyword_splat = keyword_splat
end

Public Instance Methods

describe() click to toggle source
# File lib/flexmock/validators.rb, line 201
def describe
  ".with_signature(
      required_arguments: #{self.required_arguments},
      optional_arguments: #{self.optional_arguments},
      required_keyword_arguments: #{self.required_keyword_arguments.to_a},
      optional_keyword_arguments: #{self.optional_keyword_arguments.to_a},
      splat: #{self.splat?},
      keyword_splat: #{self.keyword_splat?})"
end
expects_keyword_arguments?() click to toggle source

Whether this method may have keyword arguments

# File lib/flexmock/validators.rb, line 168
def expects_keyword_arguments?
  keyword_splat? || !required_keyword_arguments.empty? || !optional_keyword_arguments.empty?
end
keyword_splat?() click to toggle source

Whether there is a splat for keyword arguments (double-star)

# File lib/flexmock/validators.rb, line 163
def keyword_splat?
  @keyword_splat
end
null?() click to toggle source

Whether this tests anything

It will return if this validator would validate any set of arguments

# File lib/flexmock/validators.rb, line 197
def null?
  splat? && keyword_splat?
end
requires_keyword_arguments?() click to toggle source

Whether this method may have keyword arguments

# File lib/flexmock/validators.rb, line 173
def requires_keyword_arguments?
  !required_keyword_arguments.empty?
end
splat?() click to toggle source

Whether there is a positional argument splat

# File lib/flexmock/validators.rb, line 153
def splat?
  @splat
end
validate(args, kw, block) click to toggle source

Validates whether the given arguments match the expected signature

@param [Array] args @raise ValidationFailed

# File lib/flexmock/validators.rb, line 215
def validate(args, kw, block)
  kw ||= Hash.new

  if expects_keyword_arguments? && requires_keyword_arguments? && kw.empty?
    raise ValidationFailed, "#{@exp} expects keyword arguments but none were provided"
  end

  if required_arguments > args.size
    raise ValidationFailed, "#{@exp} expects at least #{required_arguments} positional arguments but got only #{args.size}"
  end

  if !splat? && (required_arguments + optional_arguments) < args.size
    raise ValidationFailed, "#{@exp} expects at most #{required_arguments + optional_arguments} positional arguments but got #{args.size}"
  end

  missing_keyword_arguments = required_keyword_arguments.
    find_all { |k| !kw.has_key?(k) }
  if !missing_keyword_arguments.empty?
    raise ValidationFailed, "#{@exp} missing required keyword arguments #{missing_keyword_arguments.map(&:to_s).sort.join(", ")}"
  end
  if !keyword_splat?
    kw.each_key do |k|
      if !optional_keyword_arguments.include?(k) && !required_keyword_arguments.include?(k)
        raise ValidationFailed, "#{@exp} given unexpected keyword argument #{k}"
      end
    end
  end
end