使用 minitest 在 rails 中设置用于控制器功能测试的请求变量

Set request variables for functional testing of controllers in rails with minitest

在 rails 中对控制器进行功能测试时,如何为请求中的测试提供动态应用程序实例变量。

我有一个 @station 对象,它在我的应用程序控制器中的 before action 中初始化(在所有其他控制器中可用),但是 @station 对象由域条目定义用户的,例如:blue.mydomain.com。所以它可以有 3 种不同的口味,控制器操作 params[:id] 只对某种口味有效。

此外,如果我不为我的测试环境添加@station 风格,它将完全失败: (这里的代码来自在我的 application_controller.rb 之前的操作中调用的助手)

def init_station
    if Rails.env == "test"
      @station=Station.new('blue')
    else
      @station=Station.new(domain_flavor_picker)
    end
end


ApplicationController
 ....
 before_action :init_station
 .....

end

因此我只能测试 'blue' 或在我之前的操作中切换风格,然后模拟不同的 id!

测试:

describe MyController do

    before do
        @id="10215d8da3f4f278cec747f09985b5528ec9e"         
    end

    it "should get index action" do
        p assigns(:station) # is nil
        get :artist_biography, id: @id, locale: I18n.available_locales.sample
        assert_response :success
        assert_not_nil assigns(:meta)           
        assert_not_nil assigns(:nav)
        assert_not_nil assigns(:content)
    end
end

如您所见,我也需要提供一个语言环境变量。我设法混淆了那个电话 I18n.available_locales.sample

如何动态切换或操作我的@station 实例变量?

assigns :station 只会 return 一个值 你做请求之后,即。在 get 行之后。在您完成请求 none 之前,您的控制器代码已 运行 用于该测试。

您也不应该在 rspec 中使用 @vars,而是使用 let,以及我在下面显示的其他一些内容,many of which I learned from BetterSpecs

问题的关键

假设 domain_flavor_picker 是你控制器中的一个方法,那么你应该模拟它,这样你就可以对它的不同 return 值进行不同的测试。因此,这显示了 domain_flavor_picker 的 return 值之一的上下文,但您需要为其他值添加其他上下文:

describe MyController do

  let(:id) { "10215d8da3f4f278cec747f09985b5528ec9e" }

  describe "GET /artist_biography" do
    context "when domain_flavor is blue" do
      before do
        allow(controller).to receive(:domain_flavor_picker) { "blue" } # <-- MOCK!
      end

      context "when valid id" do
        before { get :artist_biography, id: id, locale: I18n.available_locales.sample }

        subject { response }
        it { is_expected.to be_success }
        it "should assign :meta" do
          expect(assigns :meta).to be_present     # better to have an actual matcher here
        end
        it "should assign :nav" do
          expect(assigns :nav).to be_present      # ditto
        end
        it "should assign :content" do
          expect(assigns :content).to be_present  # ditto
        end
      end
    end
  end
end

我的问题是我需要为 minitest 提供初始主机!从@smathy 的回答我知道我需要控制器的 Mock Request

事实证明,如果你知道如何在 MiniTest 中设置它是非常容易的!

Rails 提供了一个 ActionDispatch::TestRequest 对象,它本身似乎是一个 Rack::MockRequest 对象:

DEFAULT_ENV = Rack::MockRequest.env_for('/', 'HTTP_HOST' => 'test.host', 'REMOTE_ADDR' => '0.0.0.0', 'HTTP_USER_AGENT' => 'Rails Testing' )

所以我在测试中要做的就是:

before do
  @request.env['HTTP_HOST'] = %w(blue.mydomain.com red.mydomain.com green.mydomain.com).sample
end

使用风味域样本初始化我的@station 对象。