Skip to content

Instantly share code, notes, and snippets.

@wyldrodney
Created April 4, 2012 04:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wyldrodney/2297877 to your computer and use it in GitHub Desktop.
Save wyldrodney/2297877 to your computer and use it in GitHub Desktop.
def create
@host = Host.find(params[:resource][:host_id])
@resource = @host.resources.new(path: params[:resource][:path])
if @resource.save
redirect_to '/settings/resources', notice: 'Resource was saved.'
else
@hosts = Host.order(:address)
render :new
end
end
let(:host) { mock_model(Host).as_null_object }
let(:resource) { mock_model(Resource).as_null_object }
before do
Host.stub(:find).and_return(host)
Resource.stub(:find).and_return(resource)
end
it "should redirects to index if saves" do
host.resources.should_receive(:new).and_return(resource)
resource.should_receive(:save).and_return(true)
post :create, :resource => {"path" => "/", :host_id => 1}
response.should redirect_to("/settings/resources")
end
@vessi
Copy link

vessi commented Apr 4, 2012

собственно тест начинается с 13 строчки.
вообще, суть любого теста - проверить, правильно ли работает только то, что он тестирует, не вырываясь в чужой контекст.
это, очевидно, тест для контроллера. поэтому все методы, относящиеся к моделям, здесь надо заменить заглушками - мы допускаем, что все, что выходит за пределы контекста теста - работает правильно.
поэтому сами экземпляры моделей мы заменяем заглушками (моками) при помощи метода mock_model, который создает туповатую заглушку, знающую основные методы ActiveRecord и ничего более.
перед каждым тестом у нас выполняется блок, который заставляет классы Host и Resource при вызове метода find вернуть описанные нами моки.
дальше, собственно, начинается первый тест (кстати, тесты должны покрывать все ветвления кода - там нигде ниже не было второго теста на неудачное сохранение ресурса?).
первая строчка тестируемого экшна покрылась при помощи stub (кстати, stub вызывается, когда надо сделать заглушку для метода класса, а не метода объекта - тогда используется should_receive). вторая строчка - покрывается при помощи host.resources.should_receive(:new) - и гарантированно вернет наш resource.
дальше идет условие, в котором нас для этого теста интересует первая ветка - то есть, @resource.save должно всегда вернуть true. поскольку @resource у нас равен переменной resource - мы можем застабить (поставить заглушку) вместо вызова этого метода. это делается при помощи should_receive(:имя_метода).and_return(результат)
дальше, собственно, отправляется запрос
и проверяется, что ответ у нас - редирект.

используя все это, можно легко определить, что тест на вторую ветку (если ресурс не удалось сохранить) поменяет у нас всего несколько строчек - это 23, в которой true поменяется на false, и 26, в котором будет проверка, что мы рендерим шаблон new.
response.should render_template :new
я вот только не уверен, нужно ли стабить вызов Host.order

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment