Testando o Método Create de um Controller com Nested Attributes
19 Oct 2016Como testar o método create de um controller que utiliza nested_attributes
Estava eu essa semana tentando terminar os scripts de teste de um projeto. Tudo estava dando certo, terminei de cobrir todos os testes dos models e comecei a trabalhar nos controllers, até que me deparei com o teste do método create de um controller que utiliza nested_attributes para cadastro de um model e suas associações. A estrutura dos models e controller é semelhante a essa:
# app/models/author.rb
class Author < ActiveRecord::Base
has_many :posts, dependent: :destroy
accepts_nested_attributes_for :posts, allow_destroy: true
...
end
# app/models/post.rb
class Post < ActiveRecord::Base
belongs_to :author
...
end
# app/controllers/authors_controller.rb
class AuthorsController < ApplicationController
...
def create
@author = Author.new author_params
if @author.save
flash[:success] = 'Autor cadastrado com sucesso!'
redirect_to @author
else
render 'new'
end
end
...
private
def author_params
params.require(:author).permit(:name, posts_attributes: [
:title, :content,
:id, :_destroy
])
end
...
end
Eu utilizo FactoryGirl para facilitar meus testes, a principio pesquisei por algum método mágico dessa gema que convertesse a Hash dos atributos exatamente para o aceito pelo parâmetro do controller (com nested_attributes). Passei longos 30 minutos e não achei nada, então resolvi fazer a seguinte gambiarra no script de teste:
require 'rails_helper'
RSpec.describe AuthorsController, type: :controller do
...
describe 'POST #create' do
context 'with valid attributes' do
let!(author_params) do
FactoryGirl.attributes_for(:author)
.merge(posts_attributes: [FactoryGirl.attributes_for(:post)])
end
it 'creates a new author' do
expect {
post :create, author: author_params
}.to change { Author.count }.by(1)
end
it 'redirects to :show view' do
post :create, author: author_params
expect(response).to redirect_to(Author.last)
end
end
...
end
...
end
Acredito que este não seja a forma mais correta de testar esse tipo de situação, mas pra mim deu certo.