BATCH-2761: Varargs in reader, processor, and writer builders

If a builder has a builder method that takes a List, it should also provide a builder method that takes a varargs.
This commit is contained in:
Drummond Dawson
2018-10-01 17:37:26 -04:00
committed by Mahmoud Ben Hassine
parent 2ee15d2f4c
commit 2f0c2a6772
16 changed files with 187 additions and 46 deletions

View File

@@ -16,6 +16,7 @@
package org.springframework.batch.item.data.builder;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -31,6 +32,7 @@ import org.springframework.util.StringUtils;
*
* @author Glenn Renfro
* @author Mahmoud Ben Hassine
* @author Drummond Dawson
* @since 4.0
* @see MongoItemReader
*/
@@ -41,7 +43,7 @@ public class MongoItemReaderBuilder<T> {
private Class<? extends T> targetType;
Map<String, Sort.Direction> sorts;
private Map<String, Sort.Direction> sorts;
private String hint;
@@ -175,6 +177,17 @@ public class MongoItemReaderBuilder<T> {
return this;
}
/**
* Values to be substituted in for each of the parameters in the query.
*
* @param parameterValues values
* @return The current instance of the builder
* @see MongoItemReader#setParameterValues(List)
*/
public MongoItemReaderBuilder<T> parameterValues(Object... parameterValues) {
return parameterValues(Arrays.asList(parameterValues));
}
/**
* JSON defining the fields to be returned from the matching documents by MongoDB.
*

View File

@@ -37,10 +37,10 @@ import org.springframework.util.StringUtils;
*
* @author Glenn Renfro
* @author Mahmoud Ben Hassine
* @author Drummond Dawson
* @since 4.0
* @see RepositoryItemReader
*/
public class RepositoryItemReaderBuilder<T> {
private PagingAndSortingRepository<?, ?> repository;
@@ -131,6 +131,17 @@ public class RepositoryItemReaderBuilder<T> {
return this;
}
/**
* Arguments to be passed to the data providing method.
*
* @param arguments the method arguments to be passed to the repository.
* @return The current instance of the builder.
* @see RepositoryItemReader#setArguments(List)
*/
public RepositoryItemReaderBuilder<T> arguments(Object... arguments) {
return arguments(Arrays.asList(arguments));
}
/**
* Provides ordering of the results so that order is maintained between paged queries.
*

View File

@@ -35,6 +35,7 @@ import org.springframework.util.StringUtils;
*
* @author Michael Minella
* @author Glenn Renfro
* @author Drummond Dawson
* @since 4.0
*/
public class JdbcCursorItemReaderBuilder<T> {
@@ -246,7 +247,7 @@ public class JdbcCursorItemReaderBuilder<T> {
* @param args values to set on the reader query
* @return this instance for method chaining
*/
public JdbcCursorItemReaderBuilder<T> queryArguments(Object[] args) {
public JdbcCursorItemReaderBuilder<T> queryArguments(Object... args) {
this.preparedStatementSetter = new ArgumentPreparedStatementSetter(args);
return this;

View File

@@ -31,6 +31,7 @@ import org.springframework.util.StringUtils;
*
* @author Michael Minella
* @author Mahmoud Ben Hassine
* @author Drummond Dawson
* @since 4.0.0
* @see StoredProcedureItemReader
*/
@@ -284,7 +285,7 @@ public class StoredProcedureItemReaderBuilder<T> {
* @return this instance for method chaining
* @see StoredProcedureItemReader#setParameters(SqlParameter[])
*/
public StoredProcedureItemReaderBuilder<T> parameters(SqlParameter[] parameters) {
public StoredProcedureItemReaderBuilder<T> parameters(SqlParameter... parameters) {
this.parameters = parameters;
return this;

View File

@@ -54,6 +54,7 @@ import org.springframework.util.StringUtils;
* @author Michael Minella
* @author Glenn Renfro
* @author Mahmoud Ben Hassine
* @author Drummond Dawson
* @since 4.0
* @see FlatFileItemReader
*/
@@ -183,7 +184,7 @@ public class FlatFileItemReaderBuilder<T> {
* @return The current instance of the builder.
* @see FlatFileItemReader#setComments(String[])
*/
public FlatFileItemReaderBuilder<T> comments(String[] comments) {
public FlatFileItemReaderBuilder<T> comments(String... comments) {
this.comments.addAll(Arrays.asList(comments));
return this;
}
@@ -610,7 +611,7 @@ public class FlatFileItemReaderBuilder<T> {
* @return The parent {@link FlatFileItemReaderBuilder}
* @see DelimitedLineTokenizer#setNames(String[])
*/
public FlatFileItemReaderBuilder<T> names(String [] names) {
public FlatFileItemReaderBuilder<T> names(String... names) {
this.names.addAll(Arrays.asList(names));
return this.parent;
}
@@ -691,7 +692,7 @@ public class FlatFileItemReaderBuilder<T> {
* @return This instance for chaining
* @see FixedLengthTokenizer#setColumns(Range[])
*/
public FixedLengthBuilder<T> columns(Range[] ranges) {
public FixedLengthBuilder<T> columns(Range... ranges) {
this.ranges.addAll(Arrays.asList(ranges));
return this;
}
@@ -728,7 +729,7 @@ public class FlatFileItemReaderBuilder<T> {
* @return The parent builder
* @see FixedLengthTokenizer#setNames(String[])
*/
public FlatFileItemReaderBuilder<T> names(String [] names) {
public FlatFileItemReaderBuilder<T> names(String... names) {
this.names.addAll(Arrays.asList(names));
return this.parent;
}

View File

@@ -38,6 +38,7 @@ import org.springframework.util.StringUtils;
* @author Michael Minella
* @author Glenn Renfro
* @author Mahmoud Ben Hassine
* @author Drummond Dawson
* @since 4.0
* @see FlatFileItemWriter
*/
@@ -364,7 +365,7 @@ public class FlatFileItemWriterBuilder<T> {
* @return The parent {@link FlatFileItemWriterBuilder}
* @see BeanWrapperFieldExtractor#setNames(String[])
*/
public FlatFileItemWriterBuilder<T> names(String[] names) {
public FlatFileItemWriterBuilder<T> names(String... names) {
this.names.addAll(Arrays.asList(names));
return this.parent;
}
@@ -438,7 +439,7 @@ public class FlatFileItemWriterBuilder<T> {
* @return The parent {@link FlatFileItemWriterBuilder}
* @see BeanWrapperFieldExtractor#setNames(String[])
*/
public FlatFileItemWriterBuilder<T> names(String[] names) {
public FlatFileItemWriterBuilder<T> names(String... names) {
this.names.addAll(Arrays.asList(names));
return this.parent;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017 the original author or authors.
* Copyright 2017-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@ import org.springframework.util.StringUtils;
* A builder implementation for the {@link MultiResourceItemReader}.
*
* @author Glenn Renfro
* @author Drummond Dawson
* @since 4.0
* @see MultiResourceItemReader
*/
@@ -83,7 +84,7 @@ public class MultiResourceItemReaderBuilder<T> {
*
* @see MultiResourceItemReader#setResources(Resource[])
*/
public MultiResourceItemReaderBuilder<T> resources(Resource[] resources) {
public MultiResourceItemReaderBuilder<T> resources(Resource... resources) {
this.resources = resources;
return this;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017 the original author or authors.
* Copyright 2017-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
package org.springframework.batch.item.support.builder;
import java.util.Arrays;
import java.util.List;
import org.springframework.batch.item.ItemProcessor;
@@ -26,7 +27,7 @@ import org.springframework.util.Assert;
* Creates a fully qualified {@link CompositeItemProcessorBuilder}.
*
* @author Glenn Renfro
*
* @author Drummond Dawson
* @since 4.0
*/
public class CompositeItemProcessorBuilder<I, O> {
@@ -44,6 +45,16 @@ public class CompositeItemProcessorBuilder<I, O> {
return this;
}
/**
* Establishes the {@link ItemProcessor} delegates that will work on the item to be processed.
* @param delegates the {@link ItemProcessor} delegates that will work on the item.
* @return this instance for method chaining.
* @see CompositeItemProcessorBuilder#delegates(List)
*/
public CompositeItemProcessorBuilder<I, O> delegates(ItemProcessor<?, ?>... delegates) {
return delegates(Arrays.asList(delegates));
}
/**
* Returns a fully constructed {@link CompositeItemProcessor}.
*

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017 the original author or authors.
* Copyright 2017-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
package org.springframework.batch.item.support.builder;
import java.util.Arrays;
import java.util.List;
import org.springframework.batch.item.ItemWriter;
@@ -26,7 +27,7 @@ import org.springframework.util.Assert;
* Creates a fully qualified CompositeItemWriter.
*
* @author Glenn Renfro
*
* @author Drummond Dawson
* @since 4.0
*/
public class CompositeItemWriterBuilder<T> {
@@ -67,6 +68,20 @@ public class CompositeItemWriterBuilder<T> {
return this;
}
/**
* The item writers to use as delegates. Items are written to each of the
* delegates.
*
* @param delegates the delegates to use. The delegates list must not be null
* nor be empty.
* @return this instance for method chaining.
*
* @see CompositeItemWriter#setDelegates(List)
*/
public CompositeItemWriterBuilder<T> delegates(ItemWriter<? super T>... delegates) {
return delegates(Arrays.asList(delegates));
}
/**
* Returns a fully constructed {@link CompositeItemWriter}.
*

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017 the original author or authors.
* Copyright 2017-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,6 +40,7 @@ import static org.mockito.Mockito.when;
/**
* @author Glenn Renfro
* @author Drummond Dawson
*/
public class MongoItemReaderBuilderTests {
@Mock
@@ -123,6 +124,27 @@ public class MongoItemReaderBuilderTests {
assertEquals("collection", collectionContainer.getValue());
}
@Test
public void testVarargs() throws Exception {
MongoItemReader<String> reader = getBasicBuilder()
.parameterValues("foo")
.jsonQuery("{ name : ?0 }")
.collection("collection")
.build();
ArgumentCaptor<String> collectionContainer = ArgumentCaptor.forClass(String.class);
when(this.template.find(this.queryContainer.capture(), eq(String.class), collectionContainer.capture()))
.thenReturn(new ArrayList<>());
assertNull("reader should not return result", reader.read());
Query query = this.queryContainer.getValue();
assertEquals("{ \"name\" : \"foo\" }", query.getQueryObject().toJson());
assertEquals("{ \"name\" : -1 }", query.getSortObject().toJson());
assertEquals("collection", collectionContainer.getValue());
}
@Test
public void testNullTemplate() {
validateExceptionMessage(new MongoItemReaderBuilder<String>().targetType(String.class)

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017 the original author or authors.
* Copyright 2017-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,6 +40,7 @@ import static org.mockito.Mockito.when;
/**
* @author Glenn Renfro
* @author Drummond Dawson
*/
public class RepositoryItemReaderBuilderTests {
@@ -257,6 +258,26 @@ public class RepositoryItemReaderBuilderTests {
verifyMultiArgRead(arg1Captor, arg2Captor, arg3Captor, result);
}
@Test
public void testVarargArguments() throws Exception {
ArgumentCaptor<String> arg1Captor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<String> arg2Captor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<String> arg3Captor = ArgumentCaptor.forClass(String.class);
when(this.repository.foo(arg1Captor.capture(), arg2Captor.capture(), arg3Captor.capture(),
this.pageRequestContainer.capture())).thenReturn(this.page);
RepositoryItemReader<Object> reader = new RepositoryItemReaderBuilder<>().repository(this.repository)
.sorts(this.sorts)
.maxItemCount(5)
.methodName("foo")
.name("bar")
.arguments(ARG1, ARG2, ARG3)
.build();
String result = (String) reader.read();
verifyMultiArgRead(arg1Captor, arg2Captor, arg3Captor, result);
}
public interface TestRepository extends PagingAndSortingRepository<Object, Integer> {
Object foo(PageRequest request);

View File

@@ -46,6 +46,7 @@ import static org.junit.Assert.fail;
/**
* @author Michael Minella
* @author Drummond Dawson
*/
public class JdbcCursorItemReaderBuilderTests {
@@ -156,7 +157,7 @@ public class JdbcCursorItemReaderBuilderTests {
.dataSource(this.dataSource)
.name("fooReader")
.sql("SELECT * FROM FOO WHERE FIRST > ? ORDER BY FIRST")
.queryArguments(new Integer[] {3})
.queryArguments(3)
.rowMapper((rs, rowNum) -> {
Foo foo = new Foo();

View File

@@ -46,6 +46,7 @@ import static org.junit.Assert.fail;
/**
* @author Michael Minella
* @author Mahmoud Ben Hassine
* @author Drummond Dawson
*/
public class FlatFileItemReaderBuilderTests {
@@ -55,8 +56,8 @@ public class FlatFileItemReaderBuilderTests {
.name("fooReader")
.resource(getResource("1 2 3"))
.fixedLength()
.columns(new Range[] {new Range(1, 3), new Range(4, 6), new Range(7)})
.names(new String[] {"first", "second", "third"})
.columns(new Range(1, 3), new Range(4, 6), new Range(7))
.names("first", "second", "third")
.targetType(Foo.class)
.build();
@@ -74,7 +75,7 @@ public class FlatFileItemReaderBuilderTests {
.name("fooReader")
.resource(getResource("1,2,3"))
.delimited()
.names(new String[] {"first", "second", "third"})
.names("first", "second", "third")
.targetType(Foo.class)
.build();
@@ -93,7 +94,7 @@ public class FlatFileItemReaderBuilderTests {
.resource(getResource("1 2 3"))
.delimited()
.delimiter(" ")
.names(new String[] {"first", "second", "third"})
.names("first", "second", "third")
.targetType(Foo.class)
.build();
@@ -112,7 +113,7 @@ public class FlatFileItemReaderBuilderTests {
.resource(getResource("1\t2\t3"))
.delimited()
.delimiter(DelimitedLineTokenizer.DELIMITER_TAB)
.names(new String[] {"first", "second", "third"})
.names("first", "second", "third")
.targetType(Foo.class)
.build();
@@ -133,7 +134,7 @@ public class FlatFileItemReaderBuilderTests {
.resource(getResource("1,2,3\n4,5,$1,2,3$\n@this is a comment\n6,7, 8"))
.delimited()
.quoteCharacter('$')
.names(new String[] {"first", "second", "third"})
.names("first", "second", "third")
.targetType(Foo.class)
.linesToSkip(1)
.skippedLinesCallback(skippedLines::add)
@@ -170,7 +171,7 @@ public class FlatFileItemReaderBuilderTests {
.resource(getResource("1 2%\n 3\n4 5%\n 6\n@this is a comment\n7 8%\n 9\n"))
.fixedLength()
.columns(new Range[] {new Range(1, 2), new Range(3, 5), new Range(6)})
.names(new String[] {"first", "second", "third"})
.names("first", "second", "third")
.targetType(Foo.class)
.recordSeparatorPolicy(new DefaultRecordSeparatorPolicy("\"", "%"))
.maxItemCount(2)
@@ -202,7 +203,7 @@ public class FlatFileItemReaderBuilderTests {
.name("fooReader")
.resource(new FileSystemResource("this/file/does/not/exist"))
.delimited()
.names(new String[] {"first", "second", "third"})
.names("first", "second", "third")
.targetType(Foo.class)
.strict(false)
.build();
@@ -250,9 +251,9 @@ public class FlatFileItemReaderBuilderTests {
FlatFileItemReader<Foo> reader = new FlatFileItemReaderBuilder<Foo>()
.name("fooReader")
.resource(getResource("1,2,3\n@this is a comment\n+so is this\n4,5,6"))
.comments(new String[] {"@", "+"})
.comments("@", "+")
.delimited()
.names(new String[] {"first", "second", "third"})
.names("first", "second", "third")
.targetType(Foo.class)
.build();
@@ -276,7 +277,7 @@ public class FlatFileItemReaderBuilderTests {
.name("fooReader")
.resource(getResource("1,2,3"))
.delimited()
.names(new String[] {"first", "second", "third"})
.names("first", "second", "third")
.prototypeBeanName("foo")
.beanFactory(factory)
.build();
@@ -295,7 +296,7 @@ public class FlatFileItemReaderBuilderTests {
.name("fooReader")
.resource(getResource("1,2,3"))
.delimited()
.names(new String[] {"setFirst", "setSecond", "setThird"})
.names("setFirst", "setSecond", "setThird")
.targetType(Foo.class)
.beanMapperStrict(true)
.build();
@@ -316,7 +317,7 @@ public class FlatFileItemReaderBuilderTests {
.delimited()
.includedFields(new Integer[] {0, 2})
.addIncludedField(1)
.names(new String[] {"first", "second", "third"})
.names("first", "second", "third")
.targetType(Foo.class)
.build();
@@ -383,7 +384,7 @@ public class FlatFileItemReaderBuilderTests {
}
})
.columns(new Range[] {new Range(1, 3), new Range(4, 6), new Range(7)})
.names(new String[] {"first", "second", "third"})
.names("first", "second", "third")
.targetType(Foo.class)
.build();
@@ -403,7 +404,7 @@ public class FlatFileItemReaderBuilderTests {
.resource(getResource("1 2 3"))
.fixedLength()
.columns(new Range[]{new Range(1, 3), new Range(4, 6), new Range(7)})
.names(new String[]{"first", "second", "third"})
.names("first", "second", "third")
.targetType(Foo.class)
.build();
fail("null name should throw exception");
@@ -416,7 +417,7 @@ public class FlatFileItemReaderBuilderTests {
.resource(getResource("1 2 3"))
.fixedLength()
.columns(new Range[]{new Range(1, 3), new Range(4, 6), new Range(7)})
.names(new String[]{"first", "second", "third"})
.names("first", "second", "third")
.targetType(Foo.class)
.name(null)
.build();
@@ -428,7 +429,7 @@ public class FlatFileItemReaderBuilderTests {
.resource(getResource("1 2 3"))
.fixedLength()
.columns(new Range[]{new Range(1, 3), new Range(4, 6), new Range(7)})
.names(new String[]{"first", "second", "third"})
.names("first", "second", "third")
.targetType(Foo.class)
.saveState(false)
.build());
@@ -437,7 +438,7 @@ public class FlatFileItemReaderBuilderTests {
.resource(getResource("1 2 3"))
.fixedLength()
.columns(new Range[]{new Range(1, 3), new Range(4, 6), new Range(7)})
.names(new String[]{"first", "second", "third"})
.names("first", "second", "third")
.targetType(Foo.class)
.name("foobar")
.build());
@@ -451,7 +452,7 @@ public class FlatFileItemReaderBuilderTests {
.name("fooReader")
.resource(getResource("1,2,3"))
.delimited()
.names(new String[] {"first", "second", "third"})
.names("first", "second", "third")
.targetType(Foo.class)
.build();
@@ -467,7 +468,7 @@ public class FlatFileItemReaderBuilderTests {
.encoding(encoding)
.fixedLength()
.columns(new Range[] {new Range(1, 3), new Range(4, 6), new Range(7)})
.names(new String[] {"first", "second", "third"})
.names("first", "second", "third")
.targetType(Foo.class)
.build();

View File

@@ -37,6 +37,7 @@ import static org.junit.Assert.assertTrue;
/**
* @author Michael Minella
* @author Mahmoud Ben Hassine
* @author Drummond Dawson
*/
public class FlatFileItemWriterBuilderTests {
@@ -58,10 +59,10 @@ public class FlatFileItemWriterBuilderTests {
.resource(output)
.delimited()
.delimiter(";")
.names(new String[] {"foo", "bar"})
.names("foo", "bar")
.formatted()
.format("%2s%2s")
.names(new String[] {"foo", "bar"})
.names("foo", "bar")
.build();
}
@@ -101,7 +102,7 @@ public class FlatFileItemWriterBuilderTests {
.resource(output)
.lineSeparator("$")
.delimited()
.names(new String[] {"first", "second", "third"})
.names("first", "second", "third")
.encoding("UTF-16LE")
.headerCallback(writer1 -> writer1.append("HEADER"))
.footerCallback(writer12 -> writer12.append("FOOTER"))
@@ -129,7 +130,7 @@ public class FlatFileItemWriterBuilderTests {
.lineSeparator("$")
.delimited()
.delimiter(";")
.names(new String[] {"first", "second", "third"})
.names("first", "second", "third")
.encoding("UTF-16LE")
.headerCallback(writer1 -> writer1.append("HEADER"))
.footerCallback(writer12 -> writer12.append("FOOTER"))
@@ -185,7 +186,7 @@ public class FlatFileItemWriterBuilderTests {
.lineSeparator("$")
.formatted()
.format("%2s%2s%2s")
.names(new String[] {"first", "second", "third"})
.names("first", "second", "third")
.encoding("UTF-16LE")
.headerCallback(writer1 -> writer1.append("HEADER"))
.footerCallback(writer12 -> writer12.append("FOOTER"))

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017 the original author or authors.
* Copyright 2017-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ import static org.mockito.Mockito.when;
/**
* @author Glenn Renfro
* @author Drummond Dawson
*/
public class CompositeItemProcessorBuilderTests {
@@ -68,10 +69,26 @@ public class CompositeItemProcessorBuilderTests {
assertSame(itemAfterSecondTransformation, composite.process(item));
}
@Test
public void testTransformVarargs() throws Exception {
Object item = new Object();
Object itemAfterFirstTransformation = new Object();
Object itemAfterSecondTransformation = new Object();
CompositeItemProcessor<Object, Object> composite = new CompositeItemProcessorBuilder<>()
.delegates(this.processor1, this.processor2).build();
when(processor1.process(item)).thenReturn(itemAfterFirstTransformation);
when(processor2.process(itemAfterFirstTransformation)).thenReturn(itemAfterSecondTransformation);
assertSame(itemAfterSecondTransformation, composite.process(item));
}
@Test
public void testNullOrEmptyDelegates() throws Exception {
validateExceptionMessage(new CompositeItemProcessorBuilder<>().delegates(new ArrayList<>()),
"The delegates list must have one or more delegates.");
validateExceptionMessage(new CompositeItemProcessorBuilder<>().delegates(),
"The delegates list must have one or more delegates.");
validateExceptionMessage(new CompositeItemProcessorBuilder<>(),
"A list of delegates is required.");
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017 the original author or authors.
* Copyright 2017-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@ import static org.mockito.Mockito.verify;
/**
* @author Glenn Renfro
* @author Drummond Dawson
*/
public class CompositeItemWriterBuilderTests {
@@ -58,6 +59,28 @@ public class CompositeItemWriterBuilderTests {
}
@Test
@SuppressWarnings("unchecked")
public void testProcessVarargs() throws Exception {
List<Object> data = Collections.singletonList(new Object());
List<ItemWriter<? super Object>> writers = new ArrayList<>();
ItemWriter<? super Object> writer1 = mock(ItemWriter.class);
writers.add(writer1);
ItemWriter<? super Object> writer2 = mock(ItemWriter.class);
writers.add(writer2);
CompositeItemWriter<Object> itemWriter = new CompositeItemWriterBuilder<>().delegates(writer1, writer2).build();
itemWriter.write(data);
for (ItemWriter<? super Object> writer : writers) {
verify(writer).write(data);
}
}
@Test
public void isStreamOpen() throws Exception {
ignoreItemStream(false);