问题描述
||
我对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
这里的问题是,当我尝试在随后的describe
或it
块中使用它们时,我在subject
或let
块中创建的所有灯具都已经从数据库中消失了。
例如(使用机械师创建固定装置...但是不应该如此):
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
之后?
解决方法
如果要一起使用
subject
和let
,则需要了解如何/何时调用它们。在这种情况下,在由“ 3”生成的“ 14”方法之前调用“ 2”。问题不在于在调用“ 2”之前已从数据库中删除了该对象,而是在那个时候甚至没有创建该对象。
如果您使用let!
方法,那么您的示例将起作用,该方法将添加一个before
钩子,该钩子在示例之前(因此在调用subject
之前)隐式调用user
方法。
就是说,我建议您停止努力,并使用RSpec已经公开的更简单的API:
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
在我看来,这要简单得多。
,你写了:
这里的问题是,当我尝试在以下描述或阻止中使用它们时,我在主题或let块中创建的所有固定装置都已经从数据库中消失了。
没错,就是这样。 (并且您不是使用通常的Rails含义的夹具,而是工厂-同样,因为Rails夹具很烂。)
每个单独的规范(即每个it
块)都从原始数据库开始(或应该开始)。否则,您的测试会泄漏状态并失去原子性。因此,您应该在所需的规范内创建所需的每条记录(或者,如David所说,在18英镑的代码块中减少重复)。
至于组织您的规格...请尽一切可能做。通常,整个班级都会有一个外部describe
块,对于一组需要共同设置的相关行为或规范,内部会带有describe
块。每个describe
上下文可以有自己的before
和after
块。它们像您期望的那样嵌套,因此执行的顺序类似于
外层before
内部before
规格
内部after
外层after
如果您想查看包含大量RSpec规范和Cucumber故事的项目(尽管每个版本都有较旧的版本),请访问http://github.com/marnen/quorum2。