Rails 6 中 database_cleaner 的等价物是什么?
What is an equivalent to database_cleaner in Rails 6?
我有一个规范,其中包含一个对象和两个上下文。在一种情况下,我将一个键设置为 nil 而在另一个情况下则不设置:
describe SomeClass::SomeService, type: :model do
describe '#some_method' do
subject { described_class.new(params, current_user).some_method }
mocked_params = {
min_price: 0,
max_price: 100
}
let(:params) { mocked_params }
let(:current_user) { User.create(email: 'name@mail.com') }
context 'with invalid params' do
it 'returns nil if any param is nil' do
params[:min_price] = nil
expect(subject).to eq(nil)
end
end
context 'with valid params' do
it 'returns filtered objects' do
expect(subject).to eq([])
end
end
end
end
问题是第二次测试失败了,因为min_price
仍然是零。
- 我从 Rails 5 读到我不需要
database_cleaner
。我需要还是不需要?
- 我认为
let
方法在每次看到变量时都会创建一个新对象。由于我有两个上下文,并且在两个上下文中都调用了 subject
方法,并且在 subject
中我有变量 params
,为什么 params
对象不是在每个上下文中包含所有字段的新字段?
发生这种情况是因为您仅在加载文件时初始化了 mocked_params
一次,然后在第一次测试中更改了该哈希值。
而是在 let
块中创建参数,这将导致为每个测试重新创建哈希。
改变
mocked_params = {
min_price: 0,
max_price: 100
}
let(:params) { mocked_params }
到
let(:params) do
{
min_price: 0,
max_price: 100
}
end
I read that from rails 5 on I don't need database_cleaner. Do I need
or not?
没有。不再需要了。在以前的 Rails 版本中,回滚更改的数据库事务方法仅(有时)适用于 TestUnit/Minitest 和固定装置。
I thought that the let method creates a new object every time it sees
the variable. Since I have two context, and the subject method is
called in both of them, and inside the subject I have the variable
params, why the params object is not a new one at every context? (with
all the fields)
这是完全错误的。
Use let to define a memoized helper method. The value will be cached
across multiple calls in the same example but not across examples.
当你这样做时:
mocked_params = {
min_price: 0,
max_price: 100
}
let(:params) { mocked_params }
您实际上只是返回对对象的引用 mocked_params
然后改变该对象。
如果你这样做:
let(:params) do
{
min_price: 0,
max_price: 100
}
end
您将在第一次调用 let
时获得一个新的哈希对象,然后该值将被缓存但不会在示例之间共享。但这只是该规范的冰山一角。
describe SomeClass::SomeService, type: :model do
describe '#some_method' do
let(:current_user) { User.create(email: 'name@mail.com') }
# explicit use of subject is a serious code smell!
let(:service) { described_class.new(params, current_user) }
context 'with invalid params' do
# since let is lazy loading we can define it in this context instead
let(:params) do
{
min_price: nil,
max_price: 100
}
end
it 'returns nil if any param is nil' do
# actually call the method under test instead of misusing subject
# this makes it much clearer to readers what you are actually testing
expect(service.some_method).to eq(nil)
end
end
context 'with valid params' do
let(:params) do
{
min_price: 0,
max_price: 100
}
end
it 'returns filtered objects' do
expect(service.some_method).to eq([])
end
end
end
end
为什么被测对象将散列作为第一个位置参数而不是最后一个参数也很成问题Ruby。
我有一个规范,其中包含一个对象和两个上下文。在一种情况下,我将一个键设置为 nil 而在另一个情况下则不设置:
describe SomeClass::SomeService, type: :model do
describe '#some_method' do
subject { described_class.new(params, current_user).some_method }
mocked_params = {
min_price: 0,
max_price: 100
}
let(:params) { mocked_params }
let(:current_user) { User.create(email: 'name@mail.com') }
context 'with invalid params' do
it 'returns nil if any param is nil' do
params[:min_price] = nil
expect(subject).to eq(nil)
end
end
context 'with valid params' do
it 'returns filtered objects' do
expect(subject).to eq([])
end
end
end
end
问题是第二次测试失败了,因为min_price
仍然是零。
- 我从 Rails 5 读到我不需要
database_cleaner
。我需要还是不需要? - 我认为
let
方法在每次看到变量时都会创建一个新对象。由于我有两个上下文,并且在两个上下文中都调用了subject
方法,并且在subject
中我有变量params
,为什么params
对象不是在每个上下文中包含所有字段的新字段?
发生这种情况是因为您仅在加载文件时初始化了 mocked_params
一次,然后在第一次测试中更改了该哈希值。
而是在 let
块中创建参数,这将导致为每个测试重新创建哈希。
改变
mocked_params = {
min_price: 0,
max_price: 100
}
let(:params) { mocked_params }
到
let(:params) do
{
min_price: 0,
max_price: 100
}
end
I read that from rails 5 on I don't need database_cleaner. Do I need or not?
没有。不再需要了。在以前的 Rails 版本中,回滚更改的数据库事务方法仅(有时)适用于 TestUnit/Minitest 和固定装置。
I thought that the let method creates a new object every time it sees the variable. Since I have two context, and the subject method is called in both of them, and inside the subject I have the variable params, why the params object is not a new one at every context? (with all the fields)
这是完全错误的。
Use let to define a memoized helper method. The value will be cached across multiple calls in the same example but not across examples.
当你这样做时:
mocked_params = {
min_price: 0,
max_price: 100
}
let(:params) { mocked_params }
您实际上只是返回对对象的引用 mocked_params
然后改变该对象。
如果你这样做:
let(:params) do
{
min_price: 0,
max_price: 100
}
end
您将在第一次调用 let
时获得一个新的哈希对象,然后该值将被缓存但不会在示例之间共享。但这只是该规范的冰山一角。
describe SomeClass::SomeService, type: :model do
describe '#some_method' do
let(:current_user) { User.create(email: 'name@mail.com') }
# explicit use of subject is a serious code smell!
let(:service) { described_class.new(params, current_user) }
context 'with invalid params' do
# since let is lazy loading we can define it in this context instead
let(:params) do
{
min_price: nil,
max_price: 100
}
end
it 'returns nil if any param is nil' do
# actually call the method under test instead of misusing subject
# this makes it much clearer to readers what you are actually testing
expect(service.some_method).to eq(nil)
end
end
context 'with valid params' do
let(:params) do
{
min_price: 0,
max_price: 100
}
end
it 'returns filtered objects' do
expect(service.some_method).to eq([])
end
end
end
end
为什么被测对象将散列作为第一个位置参数而不是最后一个参数也很成问题Ruby。