خطأ في اختبار وحدة التحكم rspec، طريقة غير محددة لـ nil:NilClass
-
20-12-2019 - |
سؤال
أنا جديد على 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.بهذه الطريقة، لن تضطر إلى تهتم بوضع أساليب وطوافته.فقط التركيز على اختبار طريقتك الخاصة.:)