Pergunta

Eu sou novo para o Rspec e eu estou tentando entrar em todo o BDD mentalidade, então, eu estou muito confuso sobre esse erro.Eu tenho rails engine que eu estou tentando testar.Aqui é o boletim de controlador.Basicamente, antes de qualquer ação que eu precisava para preencher a lista de cursos.

class BulletinsController < ApplicationController
  before_filter :get_courses

  def new
    @bulletin = Bulletin.new(author_id: @user.id)
  end

 ...

 private
 def get_courses
   if @user.has_role? :admin
     @course_list = Course.all.sort_by(&:start_date)
   ...
   end
 end

O aplicativo controlador possui alguns métodos que eu quero executar em cada pedido.Eu estou usando conceber o aplicativo de host para eu ter acesso ao método current_user

class ApplicationController < ::ApplicationController
  before_filter :get_user
  ...
  def get_user
    @user = current_user
  end
  ...
end

E aqui é a especificação eu estou tentando executar:

describe BulletinsController do
  routes { MyEngine::Engine.routes }
  before { controller.stub(:authenticate_user!).and_return true }
  before { controller.stub(:get_user).and_return (@user = create(:user)) }

  describe "GET #new" do
    it "assigns a new bulletin to @bulletin" do
      bulletin = create(:bulletin)
      controller.stub(:get_courses)
      get :new
      assigns(:bulletin).should eq(bulletin)
    end
  end 
end

Quando tento executar a especificação, recebo a mensagem de erro:

NoMethodError: undefined method 'id' for nil:NilClass

Eu entendo que estou conseguindo isso porque @usuário não está definido quando é chamado no boletim do edifício;no entanto, eu pensei que o antes de bloco na especificação define o @variável de usuário depois de arrancar fora o :get_user filtro.Quando faço o teste de fábricas no console, tudo parece ser criados com as associações adequadas (boletim -> autor, boletim de -curso>, etc.).

Eu não tenho certeza do que eu estou ausente por que a @variável de usuário não está sendo realizada para o meu controlador de código.Qualquer insight e/ou bons tutoriais para rspec seria muito apreciada.

Foi útil?

Solução

Eu acho que Você também precisa de stub current_user e ele vai ser o suficiente (não há necessidade de stub get_user):

before { controller.stub(:current_user).and_return (@user = create(:user)) }

E eu acho que a boa prática é deixar o usuário (se você precisa de mais do que uma vez):

routes { MyEngine::Engine.routes }
let!(:user) { create(:user) }
before { controller.stub(:current_user).and_return user }

Se você precisa de um acesso para métodos privados, você pode tentar algo como isto:

subject.send(:current_user=, user)

Poderia ser um controller em vez de subject, não tem certeza de qual a versão que suporta.

Atualização.Na verdade, é realmente complicado para testar métodos privados.Eu verifiquei que current_user no devise define como:

def current_#{mapping}
  @current_#{mapping} ||= warden.authenticate(scope: :#{mapping})
end

Assim, você pode tentar de stub warden.authenticate para retorna user:

allow_any_instance_of(Warden).to receive(:authenticate).and_return(create(:user))

Outras dicas

Tentando simular os métodos que Maquinam poderia estar usando vai ser muito difícil, a menos que você compreender como Elaborar trabalhos.

A recomendação maneira de testar é a de simplesmente entrar o usuário usando a Conceber o teste de auxiliar, conforme a sua documentação:https://github.com/plataformatec/devise#test-helpers

describe BulletinsController do
  routes { MyEngine::Engine.routes }
  before { sign_in(user) }

  let!(:user) { create(:user) }

  describe "GET #new" do
    it "assigns a new bulletin to @bulletin" do
      bulletin = create(:bulletin)
      controller.stub(:get_courses)
      get :new
      assigns(:bulletin).should eq(bulletin)
    end
  end 
end

Desta forma, você não terá que se preocupar em criar métodos e arrancar-lo.Concentre-se apenas no teste de seu próprio método.:)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top