我对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
中使用它时,我在describe
或it
块中创建的任何灯具已经从数据库中消失了{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
我正在努力解决我应该如何嵌套这些describe
和subject
以及其他块,所以也许这是我的问题,但基本上这会失败,因为当它试图让用户从数据库中,由于调用了after(:each)
挂钩,它已被删除,大概是在let
之后?
答案 0 :(得分:5)
如果您要同时使用subject
和let
,则需要了解如何/何时调用它们。在这种情况下,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
上下文都可以拥有自己的before
和after
块。这些按预期嵌套,因此执行顺序类似于
外before
内before
符合规范
内after
外after
如果你想看到一个包含大量RSpec规范和Cucumber故事的项目(虽然每个版本略有旧版本),请查看http://github.com/marnen/quorum2。