سؤال

ما هي أفضل طريقة للتعامل مع اختبار المخاوف عند استخدامها في وحدات تحكم Rails 4؟قل أن لدي قلقًا تافهًا Citations.

module Citations
    extend ActiveSupport::Concern
    def citations ; end
end

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

class ConversationController < ActionController::Base
    include Citations
end

بسيط.

ConversationController.new.respond_to? :yelling #=> true

ولكن ما هي الطريقة الصحيحة لاختبار هذا القلق بمعزل عن غيره؟

class CitationConcernController < ActionController::Base
    include Citations
end

describe CitationConcernController, type: :controller do
    it 'should add the citations endpoint' do
        get :citations
        expect(response).to be_successful
    end
end

لسوء الحظ، هذا فشل.

CitationConcernController
  should add the citations endpoint (FAILED - 1)

Failures:

  1) CitationConcernController should add the citations endpoint
     Failure/Error: get :citations
     ActionController::UrlGenerationError:
       No route matches {:controller=>"citation_concern", :action=>"citations"}
     # ./controller_concern_spec.rb:14:in `block (2 levels) in <top (required)>'

هذا مثال مفتعل.في تطبيقي، أحصل على خطأ مختلف.

RuntimeError:
  @routes is nil: make sure you set it in your test's setup method.
هل كانت مفيدة؟

المحلول

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

أنا شخصيا أجد ذلك مبالغا فيه وأفضل إجراء اختبار الوحدة بمعزل عن الآخر ثم استخدام اختبار التكامل للتأكد من سلوك وحدات التحكم الخاصة بي.

طريقة 1:دون التوجيه أو اختبار الاستجابة

إنشاء وحدة تحكم وهمية واختبار طرقها:

describe MyControllerConcern do

  before do
    class FakesController < ApplicationController
      include MyControllerConcern
    end
  end
  after { Object.send :remove_const, :FakesController }
  let(:object) { FakesController.new }

  describe 'my_method_to_test' do
    it { expect(object).to eq('expected result') }
  end

end

الطريقة الثانية:استجابة الاختبار

عندما تحتوي مخاوفك على توجيه أو تحتاج إلى اختبار الاستجابة والعرض وما إلى ذلك...تحتاج إلى إجراء الاختبار الخاص بك مع وحدة تحكم مجهولة.يسمح لك هذا بالوصول إلى جميع أساليب rspec والمساعدين المتعلقين بوحدة التحكم:

describe MyControllerConcern, type: :controller do

  controller(ApplicationController) do
    include MyControllerConcern

    def fake_action; redirect_to '/an_url'; end
  end
  before { routes.draw {
    get 'fake_action' => 'anonymous#fake_action'
  } }


  describe 'my_method_to_test' do
    before { get :fake_action }
    it { expect(response).to redirect_to('/an_url') }
  end
end

يمكنك أن ترى أنه يتعين علينا تغليف وحدة التحكم المجهولة في ملف controller(ApplicationController).إذا كانت فصولك موروثة من فئة أخرى غير ApplicationController, ، سوف تحتاج إلى التكيف مع هذا.

أيضًا لكي يعمل هذا بشكل صحيح، يجب أن تعلن في ملفك spec_helper.rb ملف:

config.infer_base_class_for_anonymous_controllers = true

ملحوظة:استمر في اختبار أن مخاوفك متضمنة

من المهم أيضًا اختبار ما إذا كانت الفئة التي تهتم بها مدرجة في الفئات المستهدفة، سطر واحد يكفي:

describe SomeTargetedController do
  describe 'includes MyControllerConcern' do
    it { expect(SomeTargetedController.ancestors.include? MyControllerConcern).to eq(true) }
  end
end

نصائح أخرى

تبسيط الطريقة الثانية من الإجابة الأكثر تصويتًا.

لكنني أفضل anonymous controller مدعوم في rspec http://www.relishapp.com/rspec/rspec-rails/docs/controller-specs/anonymous-controller

ستفعل:

describe ApplicationController, type: :controller do
  controller do
    include MyControllerConcern

    def index; end
  end

  describe 'GET index' do
    it 'will work' do
      get :index
    end
  end
end

لاحظ أنك تحتاج إلى وصف ApplicationController وقم بتعيين النوع في حالة عدم حدوث ذلك افتراضيًا.

قد تبدو إجابتي أكثر تعقيدًا بعض الشيء من إجابات @Benj و@Calin، ولكن لها مزاياها.

describe Concerns::MyConcern, type: :controller do

  described_class.tap do |mod|
    controller(ActionController::Base) { include mod }
  end

  # your tests go here
end

أولاً، أوصي باستخدام وحدة تحكم مجهولة وهي فئة فرعية من ActionController::Base, ، لا ApplicationController ولا أي وحدة تحكم أساسية أخرى محددة في التطبيق الخاص بك.بهذه الطريقة يمكنك اختبار المشكلة بمعزل عن أي من وحدات التحكم الخاصة بك.إذا كنت تتوقع أن يتم تعريف بعض الأساليب في وحدة التحكم الأساسية، فما عليك سوى إيقافها.

علاوة على ذلك، من الجيد تجنب إعادة كتابة اسم الوحدة المعنية لأنه يساعد على تجنب أخطاء النسخ واللصق.للأسف، described_class لا يمكن الوصول إليه في كتلة تم تمريرها إلى controller(ActionController::Base), ، لذلك أستخدم #tap طريقة لإنشاء ربط آخر يخزن described_class في متغير محليوهذا مهم بشكل خاص عند العمل مع واجهات برمجة التطبيقات ذات الإصدارات.في مثل هذه الحالة، من الشائع جدًا نسخ حجم كبير من وحدات التحكم عند إنشاء إصدار جديد، ومن السهل جدًا ارتكاب مثل هذا الخطأ الدقيق في النسخ واللصق.

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

giveacodicetagpre.

نهاية

قلق تحكم الخاص بي:

giveacodicetagpre.

اختبار المواصفات للقلق:

giveacodicetagpre.

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