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

每当我们的测试给我们带来意想不到的麻烦时,退后一步重新评估我们的方法很重要。通常,这表明存在一些设计问题,无论是我们正在测试的代码还是测试本身。

虽然听起来使用截断策略已经解决了这个特定问题(请参阅下面的更多内容),但我建议从这种情况中学习更多。

考虑上面规范中的两个示例。它们之间的唯一区别在于code参数是否有效。我认为这些示例实际上是在测试Group 模型,而不是控制器

现在,如果我们对模型测试覆盖率有信心,那么我们可以对控制器规范采取不同的方法。从控制器的角度来看,模型是一个协作者,一般来说,我们总是希望避免间接测试协作者。在这种情况下,我们可以使用一个 mock 来模拟模型的行为,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 回答
1

在摆弄我的 spec_helper.rb 文件之后。事实证明,我必须将我的数据库清理策略更改为截断。这是我的 spec_helper 文件,供参考(https://gist.github.com/aliibrahim/7152042

我在代码中更改了这一行并禁用了 transactional_fixtures

  config.use_transactional_fixtures = false

我的数据库清理策略现在是:

  config.before(:suite) do
    DatabaseCleaner.strategy = :truncation
    DatabaseCleaner.clean_with(:truncation)
  end

这在每个场景的开始/结束之前提供了一个清晰的数据库。希望这对任何人都有帮助!

于 2013-10-25T10:47:58.107 回答
0

你应该测试...

1)Group.create(group_params).should be_true之后group_params = ...

如果失败,则问题可能与模型或测试环境有关。

2)response.status.should == 302之后post ...

如果失败,则问题可能与会话(身份验证/授权)有关。

3)assigns(:group).should be_valid之后post ...

如果此操作失败,则问题可能与控制器有关。

于 2013-10-25T07:32:19.767 回答