Как я могу использовать хеш-сопоставитель FlexMock для проверки части значения массива? - PullRequest
0 голосов
/ 10 января 2011

Я пытаюсь проверить, что мой код на Rails вызывает метод ActiveRecord all (все это синтаксический сахар для find: all) следующим образом:

      records = Record.all
        :limit => RECORD_LIMIT, :offset => record_offset,
        :select => 'id',
        :conditions => [ 'record_type = ? AND content_score >= ?', 'user', min_content_score ],
        :order => 'content_score DESC'

Единственная часть этого кода, которая мне небезразлична в данном случае, - это параметр: condition, а меня интересует только фрагмент SQL, а не фактические значения связанных переменных. Я могу использовать средство хеширования FlexMock, чтобы утверждать, что (по крайней мере) параметр: condition присутствует следующим образом:

mock.should_receive(:all).with FlexMock.hsh :conditions => []

Однако, это соответствует только вызовам, где значение параметра: condition является пустым массивом. Что я действительно хочу, так это:

mock.should_receive(:all).with FlexMock.hsh [ 'record_type = ? AND content_score >= ?', Object, Object ]

Но, к сожалению, как показывает irb, 'user' и Object не эквивалентны:

>> '' === Object

Есть хорошие идеи? Возможны ли вложенные совпадения?

Ответы [ 2 ]

1 голос
/ 30 апреля 2011

Утиная штамповка это не должно быть необходимо. Вы можете легко определить свой собственный сопоставитель аргументов:

class HashKeyMatcher
  def initialize( key )
    @key = key
  end

  def ===( other )
    other.respond_to?( :keys ) && other.keys.include? @key
  end

  def inspect() "HashKeyMatcher( #{@key.inspect} )"; end
end

Тогда вы используете это так:

mock.should_receive(:all).
  with( HashKeyMatcher.new( :conditions ) ).
  and_return []

Поместите HashKeyMatcher где-нибудь, к чему вы сможете получить доступ из ваших тестов.

Если хотите, вы можете сделать его доступным способом, аналогичным другим сопоставителям аргументов Flexmock, открыв класс Flexmock и добавив новый метод:

class Flexmock
  def self.key( hash_key )
    HashKeyMatcher.new hash_key
  end
end

Тогда вы можете написать свой тест следующим образом:

mock.should_receive( :all ).
  with( Flexmock.key( :conditions ) ).
  and_return []
0 голосов
/ 10 января 2011

Для решения этой проблемы требуется как FlexMock для исправления обезьян, так и объект, поэтому он не для слабонервных.:)

Во-первых, monkey-patch FlexMock :: HashMatcher для вызова == объекта ожидания, а не фактического объекта:

class FlexMock::HashMatcher
  def ===(target)
    @hash.all? { |k, v| v == target[k] }
  end
end

Далее создайте объект и переопределите его ==Метод:

conditions_matcher = Object.new
conditions_matcher.instance_eval do
  def ==(other)
    other.first == 'record_type = ? AND content_score >= ?'
  end
end

Наконец, настройте ваши ожидания FlexMock:

mock.should_receive(:all).
    with(FlexMock.hsh(:conditions => conditions_matcher)).
    and_return []

Это работает для всех следующих вызовов:

Record.all :conditions => [ 'record_type = ? AND content_score >= ?' ]
Record.all :conditions => [ 'record_type = ? AND content_score >= ?', 'foo' ]
Record.all :conditions => [ 'record_type = ? AND content_score >= ?', 'foo', 5.0 ]

Ruby безумен,Но в хорошем смысле.:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...