如何使用ParameterMatchers验证数组的元素数和内容数?

时间:2015-06-17 22:01:29

标签: ruby mocha minitest

我正在使用Mocha和MiniTest学习Ruby和TDD。 我有一个有一个公共方法和许多私有方法的类,所以我的测试要测试的唯一方法是公共方法。

此公共方法执行一些处理并创建一个发送到另一个对象的数组:

def generate_pairs()
        # prepare things
        pairs = calculate_pairs()

        OutputGenerator.write_to_file(path, pairs)
    end

大。为了测试它,我想模拟OutputGenerator.write_to_file(path, pairs)方法并验证参数。我的第一次测试我可以成功实施:

def test_find_pair_for_participant_empty_participant

      available_participants = []

      OutputGenerator.expects(:write_to_file).once.with('pairs.csv', [])
      InputParser.stubs(:parse).once.returns(available_participants)

      pair = @pairGenerator.generate_pairs

    end

现在我想用一对参与者进行测试。 我正在尝试这个

 def test_find_pair_for_participant_only_one_pair

      participant = Object.new
      participant.stubs(:name).returns("Participant")
      participant.stubs(:dept).returns("D1")

      participant_one = Object.new
      participant_one.stubs(:name).returns("P2")
      participant_one.stubs(:dept).returns("D2")


      available_participants = [participant_one]

      OutputGenerator.expects(:write_to_file).once.with('pairs.csv', equals([Pair.new(participant, participant_one)])) # here it fails, of course
      InputParser.stubs(:parse).once.returns(available_participants)
      @obj.stubs(:get_random_participant).returns(participant)

      pair = @obj.generate_pairs

    end

问题是equals只会匹配obj引用,而不是内容。

有什么办法可以验证数组的内容吗?验证数组中元素的数量也非常有用。

ps:如果代码不符合ruby标准,我很抱歉,我正在做这个项目来学习语言。

1 个答案:

答案 0 :(得分:1)

你在这里测试的是一种硬耦合。这是你的主要类总是依赖于OutputGenerator,这使得测试你的输出变得棘手,如果/你必须重构你的设计会导致很多痛苦。

一个好的模式是dependency injection。有了这个,你可以编写一个临时的ruby对象,你可以用它来评估你想要的函数输出:

# in your main class...

class PairGenerator

  def initialize(opts={})
    @generator = opts[:generator] || OutputGenerator
  end

  def generate_pairs()
    # prepare things
    pairs = calculate_pairs()

    @generator.write_to_file(path, pairs)
  end

end

# in the test file...

# mock class to be used later, this can be at the bottom of the
# test file but here I'm putting it above so you are already
# aware of what it is doing
#
class MockGenerator
  attr_reader :path, :pairs

  def write_to_file(path, pairs)
    @path = path
    @pairs = pairs
  end
end

def test_find_pair_for_participant_only_one_pair

  participant = Object.new
  participant.stubs(:name).returns("Participant")
  participant.stubs(:dept).returns("D1")

  participant_one = Object.new
  participant_one.stubs(:name).returns("P2")
  participant_one.stubs(:dept).returns("D2")

  available_participants = [participant_one]

  # set up a mock generator
  mock_generator = MockGenerator.new

  # feed the mock to a new PairGenerator object as a dependency
  pair_generator = PairGenerator.new(generator: mock_generator)

  # assuming this is needed from your example
  pair_generator.stubs(:get_random_participant).returns(participant)

  # execute the code
  pair_generator.generator_pairs

  # output state is now captured in the mock, you can evaluate for
  # all the test cases you care about
  assert_equal 2, mock_generator.pairs.length
  assert mock_generator.pairs.include?(participant)
end

希望这有帮助!依赖注入并不总是合适的,但对于这样的情况它是很好的。

有关使用依赖注入的其他一些帖子可能会对您有所帮助: