【问题标题】:Rspec controller test failing when nil零时 Rspec 控制器测试失败
【发布时间】:2012-08-16 22:38:37
【问题描述】:

Rails 3.2.6

我已经按照本文的建议设置了联系人控制器和表单: http://matharvard.ca/posts/2011/aug/22/contact-form-in-rails-3/

我的Message模特班:

class Message
  include ActiveModel::Validations
  include ActiveModel::Conversion
  extend ActiveModel::Naming

  attr_accessor :name, :email, :message_body

  # validations are here...

  def initialize(attributes = {})
      attributes.each do |name, value|
      send("#{name}=", value)
      end
  end

  def persisted?
      false
  end
end

Contact Controller:

def create
    @message = Message.new(params[:message])

    if @message.valid?
        ContactMailer.new_message(@message).deliver
        redirect_to(root_path, :notice => "Message was successfully sent.")
    else
        render :new
    end
end

我的 rspec 控制器测试:

describe "POST create" do
    context "with valid information" do
      let (:message) { FactoryGirl.build(:message) }
      it "creates a new message" do
        post :create, params: message
        assigns(:message).should eq(message)
    end
  end
end

我已经通过let 验证了message 变量不为零,所以FactoryGirl 正在做它的工作。

测试结果:

ContactController POST create with valid information creates a new message
 Failure/Error: post :create, params: message
 NoMethodError:
   undefined method `each' for nil:NilClass
 # ./app/models/message.rb:14:in `initialize'
 # ./app/controllers/contact_controller.rb:8:in `new'
 # ./app/controllers/contact_controller.rb:8:in `create'
 # ./spec/controllers/contact_controller_spec.rb:22:in `block (4 levels) in <top (required)>'

我知道它失败是因为 Messageinitialize 方法。但我现在确定它为什么初始化为零。当我在开发环境中测试表单时,它似乎工作正常。感谢您的帮助。

【问题讨论】:

  • 您的it 块中似乎缺少end
  • 我将代码粘贴到 StackOverflow 时出现的错字,现已更正。
  • 我建议调试 params[:message] 的值

标签: ruby-on-rails ruby-on-rails-3 rspec


【解决方案1】:

我必须将哈希值作为值传递给post 的哈希选项。像这样:

message_attributes = FactoryGirl.attributes_for(:message)
post :create, message: message_attributes

为了比较测试中的两条消息,我不得不像这样修改Message模型:

attr_accessor :attributes, :name, :email, :message_body
def initialize(attributes = {})
    if not attributes.nil?
        attributes.each do |name, value|
            send("#{name}=", value)
        end
    end
    @attributes = attributes
end

所以最终的通过测试看起来像这样:

it "creates a new message" do
    message_attributes = FactoryGirl.attributes_for(:message)
    post :create, message: message_attributes
    assigns(:message).attributes.symbolize_keys.should eq(message_attributes)
end

我不确定这是否是最佳解决方案,但它确实创建了通过测试并验证控制器是否正确创建了消息。

【讨论】:

    【解决方案2】:

    我认为您应该使用明确的名称传递消息,如下所示:

    it "creates a new message" do
        post :create, :message => message
        assigns(:message).should eq(message)
    end
    

    或短样式:

    post :create, message: message
    

    那么你将在 params hash 中有一个键 'message'

    params[:message] = ... # here's your message
    

    否则您将没有params 中的密钥,因此params[:message] 返回 nil

    【讨论】:

    • 这仍然对我不起作用。当我用这种方法尝试时,@message 是在没有任何属性的情况下创建的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-08
    相关资源
    最近更新 更多