RSpec + DatabaseCleaner帮助 - 过早发生拆解

时间:2011-05-24 14:21:38

标签: ruby-on-rails ruby rspec datamapper

我对RSpec总是坚持使用基于xUnit的测试框架感到有些失望,但我还是试着去。

编写规范的方式的嵌套特性使我对于我应该在哪里进行数据库设置/拆卸感到头疼。

根据DatabaseCleaner自述文件:

Spec::Runner.configure do |config|

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

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end

end

现在我不能使用事务,因为我在我的代码中使用它们,所以我只是坚持截断,但这不应该在这里也不应该存在。

我有这个:

RSpec.configure do |config|
  config.mock_with :rspec

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

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end
end

这里的问题是,当我尝试在以下subject或{let中使用它时,我在describeit块中创建的任何灯具已经从数据库中消失了{1}}阻止。

例如(使用Machinist创建灯具......但这不应该相关):

describe User do
  describe "finding with login credentials" do
    let(:user) { User.make(:username => "test", :password => "password") }
    subject { User.get_by_login_credentials!("test", "password") }
    it { should == user }
  end
end

我正在努力解决我应该如何嵌套这些describesubject以及其他块,所以也许这是我的问题,但基本上这会失败,因为当它试图让用户从数据库中,由于调用了after(:each)挂钩,它已被删除,大概是在let之后?

2 个答案:

答案 0 :(得分:5)

如果您要同时使用subjectlet,则需要了解如何/何时调用它们。在这种情况下,subject会在user生成的let方法之前调用subject。问题不是在调用let!之前从db中删除了对象,而是在那时甚至没有创建它。

如果您使用before方法,您的示例将会起作用,该方法会添加user挂钩,在示例之前隐式调用subject方法(因此在describe User do it "finds a user with login credentials" do user = User.make(:username => "test", :password => "password") User.get_by_login_credentials!("test", "password").should eq(user) end end 之前调用)。

那就是说,我建议你停止挣扎并使用RSpec已经公开的更简单的API:

{{1}}

这对我来说似乎更简单。

答案 1 :(得分:3)

您写道:

  

这里的问题是,当我尝试在以下描述或阻止中使用它时,我在主题或let块中创建的任何装置已经消失(从数据库中)。

这是正确的,这就是它的工作原理。 (而且你不是在通常的Rails意义上使用灯具,而是工厂 - 同样,因为Rails灯具太糟糕了。)

每个单独的规范(即每个it块)从一个原始数据库开始(或应该开始)。否则你的测试会泄漏状态并失去原子性。所以你应该在你需要的规范中创建你需要的每一条记录(或者像David所说,在before块中减少重复)。

至于组织你的规格......以任何有意义的方式做。通常,整个类将有一个外部describe块,内部describe块用于需要通用设置的相关行为或规范组。每个describe上下文都可以拥有自己的beforeafter块。这些按预期嵌套,因此执行顺序类似于 外before
before
符合规范
after
after

如果你想看到一个包含大量RSpec规范和Cucumber故事的项目(虽然每个版本略有旧版本),请查看http://github.com/marnen/quorum2