Утверждение возвращаемого значения метода в Ruby (рецепт шеф-повара) с использованием Rspec

Я очень новичок в Rspec и пытался протестировать сценарий Ruby (это рецепт от шеф-повара) со следующим скелетом.

def foo1
   # do stuff
   list_of_names  # returns a list
end

def foo2(list_of_names)
  # do stuff
  counter = [...]
  .
  .
  counter_by_name_hash   # returns a hash
end

def main
  list = foo1
  counter_by_name_hash = foo2(list)
end

main

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

Я пробовал следующие два способа:

Во-первых: здесь я получаю ошибку NoMethodError - undefined method foo2. Не знаю, как объявить subject, так как метод foo2 находится не в классе, а в скрипте Ruby, который запускается как рецепт Chef.

it 'has valid list of names as input and returns valid hash' do
    valid_hash = {...}
    expect(subject.foo2(valid_list_of_names)).to eq(valid_hash)
end

Во-вторых: не уверен, что это утверждает возвращаемое значение, поскольку оно не выдает ошибку, даже когда я указываю неожиданное значение в части and_return.

it 'has valid list of names as input and returns valid hash' do
    valid_hash = {...}
    expect(subject).to receive(:foo2).with(valid_list_of_names).and_return(valid_hash)
    subject.foo2(valid_list_of_names)
end

На самом деле мой вопрос заключается в том, как правильно утверждать возвращаемое значение функции foo2 и как мне объявить Subject в моем файле спецификаций, если метод foo2 находится не в классе Ruby, а в рецепте? Любой вклад или помощь приветствуется.


person ka2010    schedule 26.02.2017    source источник


Ответы (1)


ИЗМЕНИТЬ:

Я не знаком с Chef, но вы можете запросить файл из своего репозитория в тесте rspec и получить доступ к его методам. Вот так:

# path/to/chef_file
def foo1
   # do stuff
   list_of_names  # returns a list
end

def foo2(list_of_names)
  # do stuff
  counter = [...]
  .
  .
  counter_by_name_hash   # returns a hash
end

def main
  list = foo1
  counter_by_name_hash = foo2(list)
end


# spec/chef_tests/my_test.rb
require 'path/to/chef_file'

describe 'Chef Tests' do
  before do
    valid_list_of_names = [...]
    valid_hash = {...}
  end

  it 'foo1 returns a valid list of names' do
    expect( foo1 ).to eq valid_list_of_names
  end

  it 'foo2 returns a valid_hash with a valid_list_of_names as input' do
    expect(foo2(valid_list_of_names)).to eq(valid_hash)
  end

end

Первый ответ:

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

class SomeClass
  class<<self
    def foo1
       # do stuff
       list_of_names  # returns a list
    end

    def foo2(list_of_names)
      # do stuff
      counter = [...]
      .
      .
      counter_by_name_hash   # returns a hash
    end

    def main
      list = foo1
      counter_by_name_hash = foo2(list)
    end
  end
end

describe SomeClass do
  before do
    valid_list_of_names = [...]
    valid_hash = {...}
  end

  it 'has valid list of names as input and returns valid hash' do
    expect(SomeClass.foo2(valid_list_of_names)).to eq(valid_hash)
  end

  it 'has valid list of names as input and returns valid hash' do
      expect(SomeClass).to receive(:foo2).with(valid_list_of_names).and_return(valid_hash)
      SomeClass.foo2(valid_list_of_names)
  end
end

Очевидно, здесь я делаю предположение, но если вы используете более строгий рубиновый способ создания экземпляра, то вы просто инициализируете объект с помощью @my_instance = SomeClass.create(...), а затем проверяете свои методы на экземпляре. Как это:

expect( @my_instance.foo2( valid_list_of_names ) ).to eq valid_hash
person James Milani    schedule 26.02.2017
comment
Поскольку этот сценарий Ruby является рецептом шеф-повара, я не могу изменить его на класс. Есть ли другой способ сделать это. - person ka2010; 26.02.2017