خطأ في اختبار وحدة التحكم rspec، طريقة غير محددة لـ nil:NilClass

StackOverflow https://stackoverflow.com//questions/24001333

سؤال

أنا جديد على Rspec وأحاول التعمق في عقلية BDD بأكملها، لذا فأنا في حيرة من أمري بشأن هذا الخطأ.لدي محرك Rails الذي أحاول اختباره.هنا وحدة تحكم النشرة.في الأساس، قبل أي إجراء، أريد ملء قائمة الدورات التدريبية.

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

تحتوي وحدة التحكم في التطبيق على بعض الطرق التي أريد تشغيلها عند كل طلب.أنا أستخدم التصميم في التطبيق المضيف حتى أتمكن من الوصول إلى طريقة المستخدم الحالي

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

وهذه هي المواصفات التي أحاول تشغيلها:

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

عندما أحاول تشغيل المواصفات، أحصل على الخطأ:

NoMethodError: undefined method 'id' for nil:NilClass

أفهم أنني أتلقى هذا لأنه لم يتم تعريف @user عند استدعائه في مبنى النشرة؛ومع ذلك اعتقدت أن الكتلة السابقة في المواصفات ستحدد متغير @user بعد إيقاف مرشح get_user :.عندما أقوم باختبار المصانع في وحدة التحكم، يبدو أن كل شيء قد تم إنشاؤه باستخدام الارتباطات المناسبة (النشرة -> المؤلف، النشرة -> الدورة التدريبية، وما إلى ذلك).

لست متأكدًا مما أفتقده بشأن سبب عدم نقل متغير @user إلى رمز وحدة التحكم الخاصة بي.أي رؤية و/أو برامج تعليمية جيدة لـ rspec ستكون موضع تقدير كبير.

هل كانت مفيدة؟

المحلول

أعتقد أنك بحاجة أيضا إلى كعب current_user وسيكون كافيًا (لا داعي للتوقف get_user):

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

وأعتقد أن الممارسة الجيدة هي السماح للمستخدم (إذا كنت في حاجة إليها أكثر من مرة):

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

إذا كنت بحاجة إلى الوصول إلى الأساليب الخاصة، فيمكنك تجربة شيء مثل هذا:

subject.send(:current_user=, user)

يمكن أن يكون أ controller بدلاً من subject, لست متأكدًا من الإصدار الذي يدعمه.

تحديث.في الواقع، من الصعب جدًا اختبار الأساليب الخاصة.لقد تأكدت من ذلك current_user في devise يحدد مثل:

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

لذلك، يمكنك أن تجرب كعب warden.authenticate للعودة user:

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

نصائح أخرى

تحاول كعب الأساليب التي يمكن أن تستخدمها مكتبة الاستبايد ستكون صعبة للغاية ما لم تفهم كيف يعمل Devise.

التوصية طريقة الاختبار هي ببساطة تسجيل الدخول المستخدم باستخدام مساعد اختبار الإقامة وفقا لتوثيقهم: https://github.com/plataformatec/devise#test-helpers

giveacodicetagpre.

بهذه الطريقة، لن تضطر إلى تهتم بوضع أساليب وطوافته.فقط التركيز على اختبار طريقتك الخاصة.:)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top