RSpec中 let
和 before
块之间有什么区别?
什么时候使用?
下面的例子中有什么好方法(让或之前)?
let(:user) { User.make !}
let(:account) {user.account.make!}
before(:each) do
@user = User.make!
@account = @user.account.make!
end
我研究了这个stackoverflow post
但是为上面的关联内容定义let是否合适?
RSpec中 let
和 before
块之间有什么区别?
什么时候使用?
下面的例子中有什么好方法(让或之前)?
let(:user) { User.make !}
let(:account) {user.account.make!}
before(:each) do
@user = User.make!
@account = @user.account.make!
end
我研究了这个stackoverflow post
但是为上面的关联内容定义let是否合适?
4 回答
人们似乎已经解释了他们不同的一些基本方式,但是没有解释为什么应该使用它们 .
我认为实例变量在绝大多数规范中都没有使用,部分原因在于this answer中提到的原因,所以我不会在这里提到它们作为选项 .
let blocks
let
块中的代码仅在引用时执行,延迟加载这意味着这些块的排序无关紧要 . 这为您提供了大量的功能,可以通过您的规格减少重复设置 .一个(非常小而且做作)的例子是:
您可以看到
has_moustache
在每种情况下的定义都不同,但不需要重复subject
定义 . 需要注意的一点是,将使用当前上下文中定义的最后一个let
块 . 这适用于设置大多数规范使用的默认值,如果需要可以覆盖 .例如,检查
calculate_awesome
的返回值,如果传递person
模型且top_hat
设置为true,但没有胡须:关于let块的另一个注意事项是,如果您正在搜索已保存到数据库中的内容(即
Library.find_awesome_people(search_criteria)
),则不应使用它们,因为它们不会保存到数据库中,除非它们已被引用 .let!
或before
块是这里应该使用的 .此外,永远 ever 使用
before
来触发let
块的执行,这就是let!
的用途!let! blocks
let!
块按照它们的定义顺序执行(很像前一个块) . 与块之前的一个核心差异是,您获得了对此变量的显式引用,而不是需要回退到实例变量 .与
let
块一样,如果使用相同的名称定义了多个let!
块,则最新的块将在执行时使用 . 如果像这样使用的话,核心区别是let!
块将被执行多次,而let
块将仅执行最后一次 .before(:each) blocks
before(:each)
是块之前的默认值,因此可以引用为before {}
,而不是每次都指定完整before(:each) {}
.在一些核心情况下,我个人倾向于使用
before
块 . 如果出现以下情况,我将使用块我正在使用 Mock ,抄写或双打
有任何合理大小的设置(通常这是您的工厂特性未正确设置的标志)
有's a number of variables which I don'需要直接引用,但是需要进行设置
我在rails中编写功能控制器测试,我想执行一个特定的测试请求(即
before { get :index }
) . 尽管在很多情况下你可以使用subject
,但如果你不需要引用,它有时会更明确 .如果您发现自己为规范编写了大块
before
块,请检查您的工厂并确保您完全了解特征及其灵活性 .before(:all) blocks
这些只在当前上下文(及其子代)中的规范之前执行过一次 . 如果正确编写,这些可以非常有用,因为在某些情况下这可以减少执行和工作量 .
一个例子(根本不会影响执行时间)是为测试模拟一个ENV变量,你应该只需要做一次 .
希望有帮助:)
几乎总是,我更喜欢
let
. 您链接的帖子指定let
也更快 . 但是,有时,当必须执行许多命令时,我可以使用before(:each)
,因为当涉及许多命令时,它的语法更清晰 .在你的例子中,我宁愿使用
let
而不是before(:each)
. 一般来说,当只进行一些变量初始化时,我倾向于使用let
.没有提到的一个很大的区别是,在第一次调用之前,用
let
定义的变量不会被实例化 . 因此,虽然before(:each)
块会实例化所有变量,let
让's you define a number of variables you might use across multiple tests, it doesn' t自动实例化它们 . 如果您希望预先加载所有数据,那么在不知道这一点的情况下,您的测试可能会回过头来咬自己 . 在某些情况下,您甚至可能希望定义一些let
变量,然后使用before(:each)
块来调用每个let
实例,以确保数据可用 .看起来你正在使用机械师 . 请注意,您可能会看到make的一些问题! let(非爆炸版本)内部发生在全局fixture事务之外(如果您也使用事务性fixture),因此破坏了其他测试的数据 .