我的问题更多的是一般性质。在处理不同类型的代码时,我已经对控制器进行了 rspec 测试,其中一些代码使用 rails 和 rspec API,而其他代码使用 mock 和存根,我开始思考。
我正在考虑使用模拟和存根而不是内置的 rails 和 rspec API 来测试控制器的优缺点是什么,如果有人可以解释哪种方法更好?
一般来说,他们可以做同样的事情(至少在某种程度上)。除了代码外观或使测试更具表现力之间的差异之外,
我的问题更多的是一般性质。在处理不同类型的代码时,我已经对控制器进行了 rspec 测试,其中一些代码使用 rails 和 rspec API,而其他代码使用 mock 和存根,我开始思考。
我正在考虑使用模拟和存根而不是内置的 rails 和 rspec API 来测试控制器的优缺点是什么,如果有人可以解释哪种方法更好?
一般来说,他们可以做同样的事情(至少在某种程度上)。除了代码外观或使测试更具表现力之间的差异之外,
如果您的问题是关于为什么要模拟和存根,那么没有简短的答案。这些任务使测试变得更加容易,因为它允许您在测试期间更好地控制软件的行为。这样,测试变得更快、更简单和更“单一”。
例如,create
在您的控制器中的一个动作中,您可能想要在模型是否保存时测试它的行为。如果您没有存根,则需要创建两个不同的实例;一个有效,另一个无效。
it "redirects to message with a notice on successful save" do
message_params = FactoryGirl.attributes_for(:message)
post :create, message_params
flash[:notice].should_not be_nil
response.should redirect_to(Message.last)
end
it "renders a :new template with a notice on unsuccessful save" do
message_params = FactoryGirl.attributes_for(:message, name: nil)
post :create, message_params
flash[:notice].should_not be_nil
response.should render_template :new
end
如您所见,有必要创建 ; 的两个实例Message
。一有效一无效。我们必须使用 FactoryGirl 来创建它们。换句话说,测试不是完全统一的,因为在创建实例时可能会出现其他问题。我们真正想要测试的是:如果保存成功,它会重定向到页面 X 吗?所以我们只想确保在一种情况下@message.valid?
返回,在另一种情况下返回。这可以使用存根轻松完成:true
false
it "should redirect to message with a notice on successful save" do
Message.any_instance.stubs(:valid?).returns(true)
post 'create'
flash[:notice].should_not be_nil
response.should redirect_to(Batch.last)
end
it "should render new template with a notice on unsuccessful save" do
Message.any_instance.stubs(:valid?).returns(false)
post 'create'
flash[:notice].should be_nil
response.should render_template('new')
end
因此,在这种情况下,测试要轻松得多,因为我们不必创建对象的实例,我们只需对方法进行存根以返回我们希望它返回的内容。使用它还有许多其他原因,您可以阅读更多关于模拟和存根的信息。
但是,如果您的问题是使用 Rspec 的内置模拟和存根功能,或者使用外部 gem,例如 Mocha,那么答案会更短:今天,我相信更多的是个人喜好。过去,像 Mocha 这样的框架有 Rspec 所没有的特性,比如any_instance
上面使用的方法。但是 Rspec 不断发展,今天它和其他产品一样好。