如何使用 ParameterMatchers 验证数组的元素数量和内容?
How do I verify the number of elements and content of an array using ParameterMatchers?
我正在学习 Ruby 使用 Mocha 和 MiniTest 的 TDD。
我有一个 class,它有一个 public 方法和许多私有方法,所以我的测试要测试的唯一方法是 public 一个。
此 public 方法进行一些处理并创建一个数组,该数组被发送到另一个对象:
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标准,我很抱歉,我正在做这个项目来学习语言。
您在这里测试的是一种硬耦合。那就是你的主要 class 总是依赖于 OutputGenerator
这使得测试你的输出变得棘手并且会导致很多痛苦 if/when 你必须重构你的设计。
一个很好的模式是 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
希望对您有所帮助!依赖注入并不总是合适的,但它非常适合这种情况。
其他一些关于使用依赖注入的帖子可能对您有帮助:
我正在学习 Ruby 使用 Mocha 和 MiniTest 的 TDD。 我有一个 class,它有一个 public 方法和许多私有方法,所以我的测试要测试的唯一方法是 public 一个。
此 public 方法进行一些处理并创建一个数组,该数组被发送到另一个对象:
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标准,我很抱歉,我正在做这个项目来学习语言。
您在这里测试的是一种硬耦合。那就是你的主要 class 总是依赖于 OutputGenerator
这使得测试你的输出变得棘手并且会导致很多痛苦 if/when 你必须重构你的设计。
一个很好的模式是 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
希望对您有所帮助!依赖注入并不总是合适的,但它非常适合这种情况。
其他一些关于使用依赖注入的帖子可能对您有帮助: