首页 > 解决方案 > rspec 测试一个类方法给对象不被监视或存根错误

问题描述

Rspec 测试

我有一个名为 Client 的课程。

class Client
  class << self
    def shutdown
      puts 'shutting down the producer gracefully'

      @producer ||= k_producer.producer(opts)
      @producer.shutdown
    end

    private
    def k_producer
      Kafka.new([127.0.0.1:9092], { required_acks: :all })
    end
  end
end

我想测试关闭类方法,但我不了解存根或间谍的概念。

我正在尝试这种方式

RSpec.describe Client do
  describe "Client.shutdown" do
    it "calls shutdown" do
      described_class.shutdown
      expect(described_class).to have_received(:shutdown)
    end
  end
end

我收到此错误,我不知道如何告诉 rspec 我的班级中有@producer,并且在其上调用了shutdown。

Client (class)> expected to have received shutdown, but that object is not a spy or method has not been stubbed

标签: rubyrspecruby-on-rails-5rspec3

解决方案


你从来没有被设置described_class为间谍。你可以通过使用allow.

RSpec.describe Client do
  describe "Client.shutdown" do
    it "calls shutdown" do
      allow(described_class).to receive(:shutdown)
      described_class.shutdown
      expect(described_class).to have_received(:shutdown)
    end
  end
end

然而,这个测试是重言式的。您只是在测试名为Client.shutdown. @producer.shutdown测试被调用的更有用。

去@producer 有点麻烦。通过为其内部对象添加访问器,我们可以使 Client 更易于测试,并且通常更灵活。

class Client
  class << self
    # Define only the writers: producer= and kafka=
    attr_writer :producer, :kafka

    # Define the readers ourselves with our defaults.
    def producer
      @producer ||= kafka.producer(opts)
    end

    def kafka
      @kafka ||= Kafka.new(["127.0.0.1:9092"], { required_acks: :all })
    end

    def shutdown
      puts 'shutting down the producer gracefully'

      producer.shutdown
    end
  end
end

现在我们制作一个间谍并将其设置为生产者。

RSpec.describe Client do
  describe "Client.shutdown" do
    it "calls @producer.shutdown" do
      producer = spy("producer")
      described_class.producer = producer
      
      described_class.shutdown

      expect(producer).to have_received(:shutdown)
    end
  end
end

推荐阅读