我正在使用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标准,我很抱歉,我正在做这个项目来学习语言。
答案 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
希望这有帮助!依赖注入并不总是合适的,但对于这样的情况它是很好的。
有关使用依赖注入的其他一些帖子可能会对您有所帮助: