Skip to content
This repository has been archived by the owner on Mar 11, 2024. It is now read-only.

Using Matchers

Biplob Biswas edited this page Sep 1, 2017 · 27 revisions

Flinkspector uses the Matcher interface from hamcrest. All Matchers provided by the framework implement Matcher<Iterable<OUT>> where OUT is the type of output records the data flow under test is producing. You can plugin any hamcrest matcher working with Iterable<OUT>:

import static org.hamcrest.Matchers.*;
//...
assertDataSet(dataSet, hasItem(Tuple2.of("value","key")));

You can apply matchers in your tests in two ways. The first is to create a TestOutputFormat or TestSink:

TestOutputFormat<Tuple2<String,String> outputFormat = 
				createTestOutputFormat(hasItem(Tuple2.of("value","key")));
dataSet.output(outputFormat);
//for data stream:
TestSink<Tuple2<String,String>> sink =
				createTestSink(hasItem(Tuple2.of("value","key")))  
dataStream.addSink(outputFormat);

The output format or sink will feed the matcher with the output of the data flow.

The second way to use a matcher on a DataSet or DataStream is:

assertDataSet(dataSet, hasItem(Tuple2.of("value","key")));
assertDataStream(dataStream, hasItem(Tuple2.of("value","key")));

In the background the framework also creates a TestOutputFormat or TestSink and adds it to the data flow, but tests become easier to read using the assert statements.

Defining a set of expected records.

For simple test cases where you just want to check if the output contains a collection of records, the best way is to use ExpectedRecords:

ExpectedRecords<String> expected = ExpectedRecords
		.create("Peter")
		.expect("Linda"))
		.expect("Klaus");
		// refine your expectations by adding requirements
output.refine().only();

The full documentation of this matcher can be found here: ExpectedRecords matcher.

Applying matchers to tuple values

If you're testing data flows producing long tuples, but only are interested in certain values. Or you wan't to apply matchers to single values in your output. Utilize AssertBlock:

OutputMatcher<Tuple2<String, Integer>> matcher =
//name the values in your tuple with keys:
new MatchTuples<Tuple2<String, Integer>>("name", "value")
//add an assertion using a value and hamcrest matchers
	.assertThat("name", isA(String.class))
	.assertThat("value", lessThan(5))
	.anyOfThem().onEachRecord();

The full documentation of this matcher can be found here: MatchTuples matcher. If your output is not in tuple form but you like to use this matcher check out: Input Output Translation.

Combining matchers

ExpectedRecords and MatchTuples both produce a hamcrest matcher, so you can utilize hamcrest's library to combine these matchers with another:

import static org.hamcrest.Matchers.*;
//...
ExpectedRecords<Tuple2<String, Integer>> output = ExpectedRecords
		.create(Tuple2.of("test", 1))
		.expect(Tuple2.of("why", 2))
		.expect(Tuple2.of("not", 3));

OutputMatcher<Tuple2<String, Integer>> matcher =
		new MatchTuples<Tuple2<String, Integer>>("name", "value")
				.assertThat("name", isA(String.class))
				.assertThat("value", lessThan(5))
				.onEachRecord();
//combine with anyOf()
assertStream(dataStream, allOf(output, hasItem(Tuple2("why",2)), matcher));

For more information on combining hamcrest matchers check out: Matchers.