gpt4 book ai didi

ruby-on-rails - 带有 RSpec 的 DRY Controller 规范

转载 作者:行者123 更新时间:2023-12-04 14:17:18 25 4
gpt4 key购买 nike

我目前正在努力使我的 Controller 规范保持干燥和简洁,并减少每个示例的一个断言。我遇到了一些困难,尤其是在嵌套结构中放置实际 Controller 请求调用以匹配各种边缘情况的位置。

这是一个示例,简化以演示问题:

describe MyController do
let(:item) { Factory(:item) }
subject { response }

describe "GET #show" do
before(:each) do
get :show
end

context "published item" do
it { should redirect_to(success_url) }
end

context "unpublished item" do
before(:each) do
item.update_attribute(published: false)
end

it { should redirect_to(error_url) }
end
end
end

显然,这是一个人为的例子,但它说明了我想做的事情和不工作的事情。主要是 before在“未发布”上下文下阻塞是问题所在。我对设置数据所做的更改实际上发生在 get 之后。由于上下文嵌套的方式调用,因此该上下文中的示例实际上是在使用初始场景而不是我想要的场景。

我理解为什么会发生这种情况以及上下文如何嵌套。我想我想要的是某种方式告诉 RSpec 我希望它在任何 before 之后立即运行什么。在给定上下文中的任何断言之前 Hook 。这对于 Controller 规范来说是完美的。我想利用我的 Controller 规范中的嵌套来逐渐建立边缘情况的变化,而不必分散 get打电话,甚至调用 do_get我的每个 it 的助手断言。与任何自定义 it_should 保持同步尤其令人讨厌。我正在使用的宏。

RSpec 目前有什么东西可以做到这一点吗?有什么技巧可以用来接近吗?它似乎非常适合我看到很多人编写 Controller 规范的方式;根据我的发现,人们基本上已经接受了 do_get。在每个断言之前调用助手。有没有更好的办法?

最佳答案

DRY 原则指出:“每条知识都必须在系统中具有单一、明确、权威的表示。”你所做的更多的是在这里和那里保存一些字符,而不是保持干燥,结果是一个层次结构上下的依赖关系错综复杂的网络,正如你所看到的,这是一个婊子去做什么你想要它,因此变得脆弱易碎。

让我们从您以冗长且有效的方式写出的内容开始:

describe MyController do
describe "GET #show" do
context "published item" do
it "redirects to the success url" do
item = Factory(:item, published: true)
get :show, :id => item.id
response.should redirect_to success_url
end
end

context "unpublished item" do
it "redirects to the error url" do
item = Factory(:item, published: false)
get :show, :id => item.id
response.should redirect_to error_url
end
end
end
end

现在唯一被复制的“知识片段”是示例的名称,可以由匹配器在每个示例的末尾生成。这可以通过使用 example 以可读的方式解决。方法,它是 it 的别名:
describe MyController do
describe "GET #show" do
context "published item" do
example do
item = Factory(:item, published: true)
get :show, :id => item.id
response.should redirect_to success_url
end
end

context "unpublished item" do
example do
item = Factory(:item, published: false)
get :show, :id => item.id
response.should redirect_to error_url
end
end
end
end

那里。干燥。并且非常易读且易于更改。现在,当您碰巧为任一上下文添加更多示例时,您可以添加 let :
describe MyController do
describe "GET #show" do
context "published item" do
let(:item) { Factory(:item, published: true) }
example do
get :show, :id => item.id
response.should redirect_to success_url
end

example do
# other example
end
end
# ...
end
end

现在唯一重复的代码(与 DRY 原则不同)是 get .如果你真的对此有强烈的感觉,你可以将这些调用委托(delegate)给像 get_show(id) 这样的方法。或类似的东西,但那时它并没有真正购买太多。它不像 get 的 API将从你下面改变,唯一的论点是 getitem的 id,您在示例中实际关心的 id(因此没有不必要的信息)。

至于使用 subject捕捉响应并让单行退出交易,这只会让事情变得非常难以阅读并且不会为您节省太多。事实上,我已经开始考虑使用 subject这样 to be a smell .

希望这一切都有帮助。

干杯,
大卫

关于ruby-on-rails - 带有 RSpec 的 DRY Controller 规范,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9267187/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com