0

我对 rspec 非常陌生,我正在尝试编写一个测试以确保创建的对象确实存在。这是我的测试现在的样子:

require 'spec_helper'

describe "UserService" do
  describe ".new" do
    it "should create a UserService object" do
      service = UserService.new
      service.should_not be_nil
    end
  end
end

问题是,我在运行测试时得到了这个输出:

  1) UserService.new should create a UserService object
     Failure/Error: service = UserService.new
     Errno::ECONNREFUSED:
       Connection refused - connect(2)
     # ./spec/requests/user_service_spec.rb:6:in `new'
     # ./spec/requests/user_service_spec.rb:6:in `block (3 levels) in <top (required)>'

我希望此时连接被拒绝,但我怎样才能测试它而不是破坏测试呢?或者,我看到的是正确的输出吗?谢谢!

4

1 回答 1

1

我看到这有两个问题。首先,您实际上是在尝试连接到测试中的外部服务。通常,您希望为被测对象提供某种代表您通常连接到的服务的模拟。我猜测您在问题中的内容以及您的代码需要进行以下更改才能正常工作的评论:

您需要构建一个外观或代理对象来“隐藏”您的 UserService 对象的真实服务。该对象基本上应该只是一对一地映射底层服务。这样做的原因是您不希望我们的内部紧密绑定到外部服务,您希望它们绑定到您的对象(并且永远不会紧密)。外观不应该进行单元测试,这会让你回到现在的位置,并且不需要进行单元测试,因为它不包含任何业务逻辑。

第二件事是您需要依赖反转来将您的 UserService 对象与特定的底层服务实现解耦。您希望您的 UserServices 构造函数获取一个对象、任何对象,并在其上调用方法来完成与服务相关的工作。由于您的 UserService 不再关心它是否是真正的服务(它不应该),您可以在测试期间为其提供一个简单的存根,而不必在外部服务缓慢或停机或以任何其他方式中断测试行为出乎意料。

第二件事是您过去常常should_not raise_error忽略测试中的特定情况。可以将它与指定的错误一起使用,例如,should_not raise_error(ConnectionError)但是当您无法自救时抛出错误是正常的事情,并且如果您稍后添加此行为,您的测试将在不应该发生的情况下中断。

测试说你应该在调用时取回一个 UserService 对象UserService.new(),它没有提到如果......在这种情况下你应该做的正确测试并记录预期的行为是给它一个工作模拟您现在拥有的测试并创建第二个测试,例如:

describe ".new" do
  it "when service is down should throw error" do
    UserService.new(offline_mock).should raise_error(ConnectionError)
  end
end

只是关于如何不以这种情况结束的一些想法开始;)像往常一样,测试中的问题通常是架构问题的标志。

于 2013-02-06T09:27:08.763 回答