ruby 中的元编程和单元测试

Meta Programming and Unit Testing in ruby

我正在使用 rspec 进行测试,虽然我不是在寻找完整的答案,但更多的是一种伪代码方法让我继续 - 我不确定如何为以下内容编写测试 class.

module AisisWriter
  class ClassFactory
    class << self
      undef_method :new
      attr_accessor :registered_objects

      def register(class_name, klass, params = nil)
        if !params.is_a(Array)
          raise ArgumentError, "params must be an array"
        end

        registered_object[class_name] = {:class_name => klass, :params => !params.nil? ? params.flatten : nil}
      end

      def create(class_name, params = nil)
        if !params.is_a(Array)
          raise ArgumentError, "params must be an array"
        end

        klass = registered_object[class_name]

        if !params.nil
          klass[:class_name].new(params.flatten)
        else
          flass[:class_name].new(*klass[:params])
        end
      end

    end
  end
end

我在 rails 中写这个 class 是为了让我注册经常使用的 classes 并能够快速创建它们。这个概念来自.

我不确定如何测试的是两件事。其中之一是我必须确保您注册的 class 确实已注册。第二,如果您尝试创建其实际创建的 class 的实例。

我可以编写一个 get_registered_objects 函数来帮助处理第一个并将其与现有对象进行比较或遍历它以查找特定属性。

但是第二部分,你如何测试 class 是否被实例化了?

为了单独测试 .register,您需要一个 getter 或者一个 .registered? 方法,它允许您访问单例的内部结构 class.

您还可以通过注册然后创建 class:

来测试 .register
describe AisisWriter::ClassFactory do
  describe '.create' do
    let(:klass) { Hash.new }
    before { AisisWriter::ClassFactory.register('Foo', ClassStub, []) }

    it "registers the class" do
      instance = AisisWriter::ClassFactory.create('Foo', [])
      expect(instance).to be_a  
    end
  end
end

除此之外,您的代码充满了问题 - 您可能想了解 class 变量的工作原理 - 以及 attr_accessor 在 class eval 中的作用。

您还可以通过以下方式降低寄存器的数量和复杂性:

def register(klass, params = nil)
  class_name = klass.name
end

Ruby在疑问句末尾使用?is_a?,nil?.