4

rspec テストの問題を解決してオブジェクトを作成しようとしていますが、何を試してもカウントが変わらないようです。ここで非常に基本的なものが欠けていると確信しています。

これが私のrspecです:

 before do
    login_account_admin(user)
    @group = Factory(:group, :code => "GR_111", :description => "description for GR_111")
    Group.stub!(:find).and_return(@group)
  end

  describe "#create" do

    it "should create a new group object" do
      group_params = {:code => "NEW_GROUP", :description => "description for NEW_GROUP"}
      expect {
        post :create, :service_id => service, :cdb_group => group_params, :button => "save", :format => "js"
      }.to change(Group, :count).by(1)
    end

    it "should not create a new group object with invalid code format" do
      group_params = {:code => "invalid", :description => "description for invalid code name group"}
      expect {
        post :create, :service_id => service, :cdb_group => group_params, :button => "save", :format => "js"
      }.to_not change(Group, :count)
    end

  end

「code」パラメーターには、大文字の A から Z、0 から 9、および _ のみを含めることができます

#create のコントローラーメソッド定義は次のとおりです。

def create
@group = Group.new(params[:cdb_group])
respond_to do |format|
  if params[:button] == "cancel"
    format.js   { render "hide_new"}
  elsif @group.save
    format.js   {
      render 'show_new_group'
    }
    format.html { redirect_to(some_path(@service), :notice => 'Group was successfully created.') }
    format.xml  { head :ok }
  end
end
end

グループモデルは次のとおりです。

class Group < ActiveRecord::Base

    validates_uniqueness_of :code
    validates_presence_of :code, :description
    validates_format_of :code, :without => /[^A-Z0-9_]/ , :message => 'can only contain uppercase letters A to Z, 0-9 and _'
end

rspec テストを実行しようとすると、次のエラーが表示されます:-

 1) GroupsController User As Account Admin goes to #create should create a new group object
 Failure/Error: expect {
   count should have been changed by 1, but was changed by 0
 # ./spec/controllers/groups_controller_spec.rb:51

 2) GroupsController User As Account Admin goes to #create should not create a new group object with invalid code format
 Failure/Error: expect {
   count should not have changed, but did change from 2 to 1
 # ./spec/controllers/groups_controller_spec.rb:58

この点で何か助けていただければ幸いです。

4

3 に答える 3

5

テストで予期しない問題が発生した場合は、一歩下がってアプローチを再評価することが重要です。通常、これは、テストしているコードまたはテスト自体に何らかの設計上の問題があることを示しています。

切り捨て戦略を使用することでこの特定の問題が解決されたように思えますが (詳細は以下を参照)、この状況から学ぶべきことが他にもあることをお勧めします。

上記の仕様の 2 つの例を考えてみましょう。それらの唯一の違いは、codeパラメーターが有効かどうかに帰着します。これらの例は実際にはコントローラではなくGroup モデルをテストしていると私は主張します。

ここで、モデルのテスト カバレッジに自信がある場合は、コントローラーの仕様に対して別のアプローチを取ることができます。コントローラーの観点からは、モデルは共同作業者であり、一般的に、共同作業者を間接的にテストすることは常に避けたいと考えています。この場合、モックを使用してGroupモデルの動作をシミュレートし、コントローラーの動作のみを分離してテストできます。

このようなもの (以下のコードは不完全でテストされていないことに注意してください):

# spec/controllers/groups_controller_spec.rb
describe "#create" do

  before do
    # use a Test Double instead of a real model
    @new_group = double(Group)
    @params = { :cdb_group => 'stub_cdb_group_param', :service_id => service }
    # using should_receive ensures the controller calls new correctly
    Group.should_receive(:new).with(@params[:cdb_group]).and_return(@new_group)
  end

  context "when cancelled responding to js" do
    it "renders hide_new" do
      post :create, @params.merge({:button => "cancel", :format => "js"})
      expect(response).to render_template('hide_new')
    end
  end

  context "with valid params" do
    before do
      @new_group.should_receive(:save).and_return(true)
    end

    context "responding to json"  # ...

    context "responding to html"  # ...

    context "responding to xml"   #...
  end

  context "with invalid params" do
    before do
      @new_group.should_receive(:save).and_return(false)
    end

    # ...
  end

end

上記はあなたが抱えていたレコード数の問題に具体的に対処していませんが、テストターゲットを正しく分離すると問題が解決する可能性があると思います.

データベースの切り捨てに固執する場合は、ここで説明されているように選択的に使用することを検討してください。

少なくともその一部が役立つことを願っています:)。

于 2013-10-26T05:47:43.143 に答える