Утверждают, что никакой метод не вызывается на макете - PullRequest
4 голосов
/ 03 декабря 2010

Я пишу тесты с Rspec2, используя фреймворк Flexmock. Я ожидаю, что один из моих методов кеширует результаты, и хочу проверить это с помощью моего макета.

describe SomeClass do
  before do
    @mock = flexmock()
  end

  after do
    @mock.flexmock_verify()
  end

  it "method caches results"
    c = SomeClass.new(@mock)
    c.method
    @mock.should_receive(:expensive_method).never
    c.method.should == ['A']
  end
end

Это хорошо работает, если я хочу убедиться, что :expensive_method никогда не вызывается. Однако я ожидаю, что мой класс сможет выполнить :method, не вызывая ничего в переданном (ложном) классе. Есть ли способ выразить это?

Справочная информация: В моем случае внедренный класс выполняет дорогостоящие операции, и поэтому результаты должны кэшироваться для одинаковых запросов.

Обновление
Спасибо за предложения, возможно, я просто предполагаю, что что-то не так или, может быть, то, что я хочу, даже не имеет смысла. Я реализовал кеширование путем удержания переменной класса в SomeClass и добавления к этому в :method:

def SomeClass
  @@cache_map = {}

  def method
    # extract key
    return @@cache_map[key] if @@cache_map.has_key?(key)
    # call :expensive_method to get result
    @@cache_map[key] = result
    return result
  end
end

Теперь, чтобы проверить правильность кэширования, мне нужно хотя бы один раз вызвать :extensive_method, чтобы загрузить кеш. Мне нравится решение Дэвида Челимски, но оно не отвечает моему первоначальному намерению, а именно: проверить, что после первого вызова SomeClass.method введенный класс больше никогда не вызывается (ни :expensive_method, ни что-либо еще).

Ответы [ 2 ]

9 голосов
/ 16 июня 2011

Обычный способ указать кэширование - это сказать @mock.should_receive(:expensive_method).once перед тем, как вообще вызвать method, а затем вызвать метод, который вызывает его дважды.

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

describe Client do
  let(:service) { flexmock() }
  let(:client)  { Client.new(service) }

  it "uses data retrieved from service" do
    service.stub(:expensive_method).and_return('some data')
    client.method.should eq('some data')
  end

  it "only retrieves the data once" do
    service.should_receive(:expensive_method).once
    client.method
    client.method
  end
end

Кроме того, вам не нужно вызывать flexmock_verify, как это происходит автоматически.

1 голос
/ 16 июня 2011

Конечно, не устанавливая каких-либо ожиданий на макетируемом объекте, это будет достигнуто.Любой вызов, сделанный с имитатором, приведет к неожиданному сбою вызова (я признаю, что никогда не использовал Flexmock, но все другие фреймворки, которые я использовал, работают таким образом).

К сожалению, нетдействительно любой способ сделать это явным в тесте.Возможно, измените имя теста, чтобы указать его, возможно, что-то вроде «метод использует кэшированный результат без вызова смоделированного объекта».

...