【问题标题】:How can I determine the subject of an rspec controller test?如何确定 rspec 控制器测试的主题?
【发布时间】:2026-01-03 18:25:01
【问题描述】:

因此,除了好奇之外,我没有充分的理由需要知道这一点——这是最好的理由——但我不确定这里发生了什么。

背景:
我正在阅读 RSpec 书并更新示例。

在第 24 章 - Rails 控制器中,有一个消息控制器的测试。

## spec/controllers/messages_controller_spec.rb ##

require 'spec_helper'

describe MessagesController do
  describe "POST create" do
    let(:message) { mock_model(Message).as_null_object }

    before do
      Message.stub(:new).and_return(message)
    end

  # Then a bunch of Tests...

    context "when the message fails to save" do
      before do
        message.stub(:save).and_return(false)
        post :create
      end

      it "assigns @message" do
        assigns[:message].should eq(message)
      end

      it "renders the new template" do
        response.should render_template("new")
      end
    end
  end
end

这与消息控制器一起使用:

## app/controllers/messages_controller.rb ##

class MessagesController < ApplicationController
  def create
    @message = Message.new(params[:message])

    if @message.save
      flash[:notice] = "The message was saved successfully"
      redirect_to action: "index"
    else
      render "new"
    end
  end
end



当我运行测试时:

测试通过响应

it "renders the new template" do
  response.should render_template("new")
end

测试也通过了主题

it "renders the new template" do
  subject.should render_template("new")
end

测试也通过 page

it "renders the new template" do
  page.should render_template("new")
end

测试也通过 NOTHING

it "renders the new template" do
 should render_template("new")
end

如果它有助于任何人对此有所了解,config/routes.rb 就只有 resources :messages

为什么所有这些测试都通过了?我实际上在测试什么? “页面”、“主题”和“”只是响应的同义词吗? 只要我的测试通过就重要吗?

【问题讨论】:

    标签: ruby-on-rails rspec controller tdd rspec-rails


    【解决方案1】:

    默认情况下,主题将引用类,即 MessagesController。

    在上一个测试示例中未定义主题,将隐式设置主题为 MessagesController。

    【讨论】:

    • 这并不能真正回答问题,但这主要是我的错,因为没有更清楚。回应是什么?这里实际发生了什么。响应只是附加到 MessagesController 类的对象吗?很抱歉要求澄清。我想接受答案,但我仍然不明白这里发生了什么。
    • 查看文档 guides.rubyonrails.org/v2.3.11/… 是 MessagesController 类的响应,在测试控制器时,如果您的 it ... do 块将主题定义为类本身,则应该等同于我认为的响应对象
    【解决方案2】:

    从 binding.pry 看来,subject 是控制器类的 实例

    [2] pry(#<RSpec::ExampleGroups::MyController::DescribeString::ContextString>)> subject.is_a? Class
    => false
    [3] pry(#<RSpec::ExampleGroups::MyController::DescribeString::ContextString>)> subject.is_a? Users::SessionsController
    => true
    

    【讨论】: