1

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

这个公共方法做一些处理并创建一个发送给另一个对象的数组:

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标准,我很抱歉,我正在做这个项目来学习语言。

4

1 回答 1

1

您在这里测试的内容展示了一种硬耦合。那是您的主要课程始终取决于OutputGenerator哪个使测试您的输出变得棘手,并且如果/当您必须重构设计时可能会导致很多痛苦。

一个很好的模式是依赖注入。有了这个,你可以写一个临时的 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

希望这可以帮助!依赖注入并不总是合适的,但它非常适合这种情况。

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

于 2015-06-18T01:39:49.493 回答