© 2020 - 2022 by Alexei Klenin
Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.
1. Preface
@InjectResources
is a Java library providing simple and convenient way to load and parse resource files. It does all
opening and closing of input streams and handles exceptions.
Java 8+ is required in order to use this library.
2. Modules
Library composed of following modules:
3. Java DSL
@InjectResources
fluid Java DSL helps to load and parse the resources conveniently.
3.1. Dependency
Add inject-resources-core
dependency to your project.
Using Maven:
<dependency>
<groupId>io.hosuaby</groupId>
<artifactId>inject-resources-core</artifactId>
<version>0.2.2</version>
</dependency>
Or using Gradle:
compile group: 'io.hosuaby', name: 'inject-resources-core', version: '0.2.2'
3.2. Java DSL example
var text = resource()
.withPath("/com/adelean/junit/jupiter", "resource.txt")
.text();
3.2.1. Entry point
Method InjectResources#resource
is an entry point of Java DSL. It’s recommended to import this method statically:
import static com.adelean.inject.resources.core.InjectResources.resource;
3.2.2. Choosing the classloader
To choose a classloader used to load a single resource it’s possible to use resource().onClassLoader(classLoader)
or
resource().onClassLoaderOf(clazz)
.
Example:
var text = resource()
.onClassLoader(this.getClass().getClassLoader())
.withPath("/com/adelean/junit/jupiter", "resource.txt")
.text();
// or
var text = resource()
.onClassLoaderOf(this.getClass())
.withPath("/com/adelean/junit/jupiter", "resource.txt")
.text();
We can omit the choice of a classloader with resource().withPath(path)
. In that case the context classloader
Thread.currentThread().getContextClassLoader()
is used.
3.2.3. Specifying path to resource
Method withPath(path)
allows to define the path to the requested resource. The next three notations are equivalents:
// There notations are equivalent
resource().withPath("/com/adelean/junit/jupiter/resource.txt");
resource().withPath("/com/adelean/junit/jupiter", "resource.txt");
resource().withPath("com", "adelean", "junit", "jupiter", "resource.txt");
3.2.4. Read text content
Content of a text resource can be read as String
using method text()
:
var text = resource().withPath("resource.txt").text();
// or with specified charset
var text = resource().withPath("resource.txt").text(StandardCharsets.UTF_8);
3.2.5. Read binary content
Content of a binary resource can be read as byte[]
using method bytes()
:
var fibonacci = resource().withPath("fibonacci.bin").bytes();
3.2.6. Parsing of resource content
In order to parse resources content, need to get one of provided wrappers around that resource. Wrapper can be obtained by calling one of the those methods:
-
asInputStream()
- returns wrapper around resource represented as anInputStream
. -
asByteArray()
- resource as bytes array. -
asReader()
- resource asReader
. Can also beasReader(Charset charset)
. -
asLines()
- resource as a stream of text lines. Can also beasLines(Charset charset)
. -
asText()
- resource as text. Can also beasText(Charset charset)
.
Those wrappers (except those returned by asLines()
) expose four methods that can be used to process content of a resource:
-
parse(Function<I, O> parsingFunction)
- parses content of resource usingparsingFunction
. -
parseChecked(ThrowingFunction<I, O> parsingFunction)
- parses content of resource usingparsingFunction
that may throw exception. -
then(Consumer<I> contentConsumer)
- processes content of resource usingcontentConsumer
. -
thenChecked(ThrowingConsumer<I> contentConsumer)
- processes content of resource usingcontentConsumer
that may throw exception.
Ignoring uncaught exceptions
Two new functional interfaces are provided by the library: ThrowingFunction
and ThrowingConsumer
. They are similar to
interfaces Function
and Consumer
from java.util.function
but they are able to capture lambdas that may throw a
checked exception. Example:
// Instead of this
var dbConnection = resource()
.withPath("db.properties")
.asInputStream()
.parse(inputStream -> {
try {
return reader.readValue(inputStream);
} catch (IOException parsingException) {
throw new RuntimeException(parsingException);
}
});
// We can write this
var dbConnection = resource()
.withPath("db.properties")
.asInputStream()
.parseChecked(reader::readValue);
Read resource line by line
The resource wrapper returned by method asLines()
able to process text resource file line by line. It’s practical to parse
resources in line based formats, like CSV. Example:
var header = new AtomicReference<String>();
var lines = new ArrayList<String>();
resource()
.withPath("cities.csv")
.asLines()
.onFirstLine(header::set)
.forEachLine(lines::add);
4. Spring module
@InjectResources
module for convenient resource injection in your Spring application.
This module is alternative to ResourceLoader and ResourceUtils from Spring.
4.1. Dependency
Add inject-resources-spring
dependency to your project.
Using Maven:
<dependency>
<groupId>io.hosuaby</groupId>
<artifactId>inject-resources-spring</artifactId>
<version>0.2.2</version>
</dependency>
Or using Gradle:
compile group: 'io.hosuaby', name: 'inject-resources-spring', version: '0.2.2'
4.2. Enabling resource injection
To enable resource injection annotation any spring configuration with @EnableResourceInjection
.
Example:
@Configuration
@EnableResourceInjection
public class MyConfig {
}
Then you can use resource annotations to inject content of resources into your beans:
@Component
public class MyBean {
@BinaryResource("/com/adelean/junit/jupiter/fibonacci.bin") (1)
private byte[] fibonacciInstanceField;
@Autowired
public MyBean(
@TextResource("/com/adelean/junit/jupiter/resource.txt") (2)
String text) {
// ...
}
@JsonResource(from = "/com/adelean/junit/jupiter/sponge-bob.json", parserBean = "defaultObjectMapper") (3)
public void setParsedJson(Person parsedJson) {
// ...
}
}
1 | Injects binary content into instance field |
2 | Injects text content into constructor argument |
3 | Injects JSON parsed as POJO into setter |
4.3. Resource annotations
Resource annotations can annotate beans field, constructor argument or setter method that must be injected with content of resource file.
The following sections present those available resource annotations and their usage.
4.3.1. Binary resources
Given a resource /com/adelean/junit/jupiter/fibonacci.bin
with binary content:
1 1 2 3 5 8 13 21 34 55 89
Inject the content of that resource using annotation @BinaryResource
:
@Component
class MyBean {
@BinaryResource("/com/adelean/junit/jupiter/fibonacci.bin")
private byte[] fibonacci;
}
4.3.2. Text resources
Assuming there is a resource /com/adelean/junit/jupiter/resource.txt
containing
The quick brown fox jumps over the lazy dog.
Content of that resource can be injected using annotation @TextResource
:
@Component
class MyBean {
@TextResource("/com/adelean/junit/jupiter/resource.txt")
private String instanceField;
}
4.3.3. Properties resources
Given a properties resource /com/adelean/junit/jupiter/db.properties
with content:
db.user=hosuaby
db.password=password
db.url=localhost
These properties can be injected using annotation @PropertiesResource
:
@Component
class MyBean {
@PropertiesResource("/com/adelean/junit/jupiter/db.properties")
private Properties dbProperties;
}
4.3.4. JSON and JSON Lines resources
Annotations JsonResource
and JsonLinesResource
can be used to load and parse content of resources in formats JSON
and JSON Lines (one JSON document per line) respectively. They rely on popular libraries, Jackson or Gson to
parse content into multiple Java types like Map<String, Object>
, JsonNode
(for Jackson) & JsonElement
(for GSON) or to Java POJO.
In order to use those annotations bean of type com.fasterxml.jackson.databind.ObjectMapper
from
Jackson or com.google.gson.Gson
from
GSON must be present in application context.
JsonResource
and JsonLinesResource
have a property parserBean
that allows to specify the name of used parser bean
in case where there are multiple ObjectMapper
or Gson
beans in context. If value of that property is empty, the
first found or primary bean if those types are used.
Example with Jackson
@Configuration
@EnableResourceInjection
public class JacksonConfig {
@Bean
@Primary
public ObjectMapper defaultObjectMapper() {
return new ObjectMapper();
}
@Bean
public ObjectMapper logsObjectMapper() {
return new ObjectMapper()
.registerModule(new JavaTimeModule());
}
}
@Component
public class MyBean {
/* JSON resources */
@JsonResource("/com/adelean/junit/jupiter/sponge-bob.json")
static Map<String, Object> jsonAsMap;
@JsonResource(from = "/com/adelean/junit/jupiter/sponge-bob.json", parserBean = "defaultObjectMapper")
JsonNode jsonNode;
@JsonResource("/com/adelean/junit/jupiter/sponge-bob.json")
Person spongeBob;
/* JSONL resources */
@JsonLinesResource(from = "/com/adelean/junit/jupiter/logs.jsonl", parserBean = "logsObjectMapper")
private Log[] logsAsArray;
@JsonLinesResource(from = "/com/adelean/junit/jupiter/logs.jsonl", parserBean = "logsObjectMapper")
private Collection<Log> logsAsCollection;
}
Example with Gson
@Configuration
@EnableResourceInjection
public class GsonConfig {
@Bean
@Primary
public Gson defaultGson() {
return new Gson();
}
@Bean
public Gson logsGson() {
return new GsonBuilder()
.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeDeserializer())
.create();
}
}
@Component
public class MyBean {
/* JSON resources */
@JsonResource("/com/adelean/junit/jupiter/sponge-bob.json")
private static Map<String, Object> jsonAsMap;
@JsonResource("/com/adelean/junit/jupiter/sponge-bob.json")
protected JsonElement jsonElement;
@JsonResource("/com/adelean/junit/jupiter/sponge-bob.json")
Person spongeBob;
/* JSONL resources */
@JsonLinesResource(from = "/com/adelean/junit/jupiter/logs.jsonl", parserBean = "logsGson")
private Log[] logsAsArray;
@JsonLinesResource(from = "/com/adelean/junit/jupiter/logs.jsonl", parserBean = "logsGson")
private Collection<Log> logsAsCollection;
}
4.3.5. YAML and YAML documents resources
Annotations YamlResource
and YamlDocumentsResource
can be used to parse content of resources in formats YAML and
YAML documents (multiple YAML documents in the same file separated by three hyphens ---). Bean of type
org.yaml.snakeyaml.Yaml
from Snakeyaml must be present in
application context.
Example:
@Configuration
@EnableResourceInjection
public class YamlConfig {
@Bean
@Primary
public Yaml defaultYaml() {
return new Yaml();
}
@Bean("log-parser")
public Yaml logYaml() {
return new Yaml(new Constructor(Log.class));
}
}
@Component
public class MyBean {
/* YAML resources */
@YamlResource("/com/adelean/junit/jupiter/receipt.yml")
Map<String, Object> receipt;
@YamlResource("/com/adelean/junit/jupiter/sponge-bob.yaml")
Person spongeBob;
/* YAML documents resources */
@YamlDocumentsResource(from = "/com/adelean/junit/jupiter/stacktrace.yaml", yamlBean = "defaultYaml")
List<Map<String, Object>> stacktraceAsList;
@YamlDocumentsResource(from = "/com/adelean/junit/jupiter/stacktrace.yaml", yamlBean = "defaultYaml")
Map<String, Object>[] stacktraceAsArray;
@YamlDocumentsResource(from = "/com/adelean/junit/jupiter/logs.yml", yamlBean = "log-parser")
Log[] logsAsArray;
@YamlDocumentsResource(from = "/com/adelean/junit/jupiter/logs.yml", yamlBean = "log-parser")
Collection<Log> logsAsCollection;
}
5. JUnit Jupiter extension
@InjectResources
JUnit Jupiter extension gives ability to inject content of resources into JUnit5 tests.
5.1. Dependency
Add inject-resources-core
and inject-resources-junit-jupiter
dependencies to your project.
Using Maven:
<dependency>
<groupId>io.hosuaby</groupId>
<artifactId>inject-resources-core</artifactId>
<version>0.2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.hosuaby</groupId>
<artifactId>inject-resources-junit-jupiter</artifactId>
<version>0.2.2</version>
<scope>test</scope>
</dependency>
Or using Gradle:
testCompile group: 'io.hosuaby', name: 'inject-resources-core', version: '0.2.2'
testCompile group: 'io.hosuaby', name: 'inject-resources-junit-jupiter', version: '0.2.2'
5.2. Test extension
In order to use this plugin, we need to add extension to the test class:
@TestWithResources // add JUnit Jupiter extension
class InjectResourcesTests {
}
5.3. Resource content injection
To inject content of resource files in our tests we need to use one of the @Given*
annotations (called resource
annotations). Resource annotations can be placed on static
class fields, instance fields and parameters of test
methods. Injected fields must be non-private and non-final.
@TestWithResources
class InjectResourcesTests {
@GivenTextResource("/com/adelean/junit/jupiter/resource.txt") (1)
static String classField;
@GivenTextResource("/com/adelean/junit/jupiter/resource.txt") (2)
String instanceField;
@Test
public void testWithResources(
@GivenTextResource("/com/adelean/junit/jupiter/resource.txt") (3)
String testParameter) {
}
}
1 | Inject into static class field |
2 | Inject into instance field |
3 | Inject into test parameter |
5.4. Load binary resource
Given a resource /com/adelean/junit/jupiter/fibonacci.bin
with binary content:
1 1 2 3 5 8 13 21 34 55 89
Inject the content of that resource using annotation @GivenBinaryResource
:
@TestWithResources
class InjectBinaryResourcesTests {
@GivenBinaryResource("/com/adelean/junit/jupiter/fibonacci.bin")
byte[] fibonacci;
@Test
public void testInjectBinaryContentIntoByteArrayInstanceField() {
assertThat(fibonacci)
.contains(1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89);
}
}
5.5. Load text resource
Assuming there is a resource /com/adelean/junit/jupiter/resource.txt
containing
The quick brown fox jumps over the lazy dog.
Content of that resource can be injected into test using annotation @GivenTextResource
:
@TestWithResources
class InjectTextResourcesTests {
@GivenTextResource("/com/adelean/junit/jupiter/resource.txt")
String instanceField;
@Test
public void testInjectTextIntoStringInstanceField() {
assertThat(instanceField)
.isEqualTo("The quick brown fox jumps over the lazy dog.");
}
}
5.6. Load properties resources
Given a properties resource /com/adelean/junit/jupiter/db.properties
with content:
db.user=hosuaby
db.password=password
db.url=localhost
These properties can be injected into tests using annotation @GivenPropertiesResource
:
@TestWithResources
class InjectPropertiesResourcesTests {
@GivenPropertiesResource("/com/adelean/junit/jupiter/db.properties")
Properties dbProperties;
@Test
public void testInjectTextIntoStringInstanceField() {
assertThat(dbProperties)
.containsEntry("db.user", "hosuaby")
.containsEntry("db.password", "password")
.containsEntry("db.url", "localhost");
}
}
5.7. Load and parse JSON
This library simplifies loading and parsing of JSON & JSONL (JSON Lines) files. Native support for
Jackson and GSON
gives ability to parse JSON content into Map<String, Object>
, JsonNode
(for Jackson) & JsonElement
(for GSON) or to Java POJO.
Use annotation @GivenJsonResource
for JSON and @GivenJsonLinesResource
for JSONL.
In order to parse JSON/JSONL we need to declare a parser. Parsers are fields or functions that are annotated with
@With*
annotations.
/* Jackson */
@WithJacksonMapper
ObjectMapper objectMapper = new ObjectMapper();
/* or GSON */
@WithGson
Gson gson = new Gson();
Following subsections explain how to parse JSON/JSONL with Jackson or GSON in detail.
5.7.1. Jackson
In order to parse resources with Jackson both jackson-core
& jackson-databind
must be present on the Classpath.
To specify which ObjectMapper
is used to parse JSON use annotation @WithJacksonMapper
:
@WithJacksonMapper
ObjectMapper objectMapper = new ObjectMapper();
Configure your parser as you need:
@WithJacksonMapper
ObjectMapper objectMapper = new ObjectMapper()
.registerModule(new JavaTimeModule());
Now you can inject content of JSON/JSONL into your tests:
@TestWithResources
class TestsWithJackson {
@WithJacksonMapper
ObjectMapper objectMapper = new ObjectMapper()
.registerModule(new JavaTimeModule());
/* JSON */
@GivenJsonResource("/com/adelean/junit/jupiter/sponge-bob.json")
Map<String, Object> jsonAsMap;
@GivenJsonResource("/com/adelean/junit/jupiter/sponge-bob.json")
JsonNode jsonNode;
@GivenJsonResource("/com/adelean/junit/jupiter/sponge-bob.json")
Person spongeBob;
/* JSONL */
@GivenJsonLinesResource("/com/adelean/junit/jupiter/logs.jsonl")
Log[] logsAsArray;
@GivenJsonLinesResource("/com/adelean/junit/jupiter/logs.jsonl")
Collection<Log> logsAsCollection;
}
5.7.2. GSON
To parse JSON/JSONL resources with GSON, com.google.code.gson:gson
must be present on Classpath.
Declare GSON object used to parse resources and annotate it with @WithGson
:
@WithGson
Gson gson = new Gson();
Now you can inject content of JSON/JSONL into your tests:
@TestWithResources
class TestsWithGson {
@WithGson
Gson gson = new GsonBuilder();
/* JSON */
@GivenJsonResource("/com/adelean/junit/jupiter/sponge-bob.json")
Map<String, Object> jsonAsMap;
@GivenJsonResource("/com/adelean/junit/jupiter/sponge-bob.json")
JsonElement jsonElement;
@GivenJsonResource("/com/adelean/junit/jupiter/sponge-bob.json")
Person spongeBob;
/* JSONL */
@GivenJsonLinesResource("/com/adelean/junit/jupiter/logs.jsonl")
Log[] logsAsArray;
@GivenJsonLinesResource("/com/adelean/junit/jupiter/logs.jsonl")
Collection<Log> logsAsCollection;
}
5.8. Load and parse YAML
Thanks to native support of Snakeyaml library is able to
parse YAML resources files. org.yaml:snakeyaml
must be present on Classpath in order to use that feature.
Declare Yaml
object used for parsing and annotate it with @WithSnakeYaml
:
@WithSnakeYaml
Yaml yaml = new Yaml();
Resource annotations @GivenYamlResource
and @GivenYamlDocumentsResource
can be now used to parse YAML with single
or multiple documents respectively:
@TestWithResources
class TestsWithYaml {
@WithSnakeYaml
Yaml yaml = new Yaml();
/* YAML resource with a single document */
@GivenYamlResource("/com/adelean/junit/jupiter/receipt.yml")
Map<String, Object> receipt;
@GivenYamlResource("/com/adelean/junit/jupiter/sponge-bob.yaml")
Person spongeBob;
/* YAML resource with multiple documents separated by '---' */
@GivenYamlDocumentsResource("/com/adelean/junit/jupiter/stacktrace.yaml")
List<Map<String, Object>> stacktraceAsList;
}
Yaml
object must be configured to be able to parse documents from multi-document YAML into POJO:
@TestWithResources
class TestsWithYaml {
/* Assuming we have defined class Log */
@WithSnakeYaml("log-parser")
Yaml logParser = new Yaml(new Constructor(Log.class));
@GivenYamlDocumentsResource(from = "/com/adelean/junit/jupiter/logs.yml", yaml = "log-parser")
Log[] logsAsArray;
}
5.9. Parsers
This section talks about objects annotated with @With*
annotations. Those objects are called parsers. Annotations
@With*
are called parser annotations. They can annotate class and instance fields or methods of test classes.
// Parser object from field
@WithJacksonMapper
ObjectMapper objectMapper = new ObjectMapper();
// Parser object from function
@WithJacksonMapper("custom-mapper")
ObjectMapper objectMapper() {
return new ObjectMapper().registerModule(new JavaTimeModule());
}
Parsers can be named or anonymous. Named parsers are useful when some resources require a special configuration of parser.
In following example, resource /com/adelean/junit/jupiter/logs.jsonl
is parsed by ObjectMapper
named
"custom-mapper".
@TestWithResources
class TestsWithNamedParser {
// Named parser
@WithJacksonMapper("custom-mapper")
ObjectMapper objectMapper = new ObjectMapper()
.registerModule(new JavaTimeModule());
// JSONL resource parser by parser named 'custom-mapper'
@GivenJsonLinesResource(
from = "/com/adelean/junit/jupiter/logs.jsonl",
jacksonMapper = "custom-mapper")
Collection<Log> logsAsCollection;
}
5.9.1. Parser scopes
By default, parsers are scoped to test class where they were defined. If a test class inherits from another class, parsers defined in superclass can be used in subclass:
abstract class SuperClassWithParser {
@WithJacksonMapper("custom-mapper")
ObjectMapper objectMapper = new ObjectMapper()
.registerModule(new JavaTimeModule());
}
@TestWithResources
class TestsSubclass extends SuperClassWithParser {
@GivenJsonLinesResource(
from = "/com/adelean/junit/jupiter/logs.jsonl",
jacksonMapper = "custom-mapper")
Collection<Log> logsAsCollection;
}
5.9.2. Tests advice
It is possible to define a parser that can be used by all tests on the Classpath by creating a public
final
class
annotated with @TestsAdvice
:
@TestsAdvice
public final class GlobalJacksonMapper {
@WithJacksonMapper("custom-mapper")
ObjectMapper objectMapper() {
return new ObjectMapper().registerModule(new JavaTimeModule());
}
}
@TestWithResources
class TestsWithJson {
@GivenJsonLinesResource(
from = "/com/adelean/junit/jupiter/logs.jsonl",
jacksonMapper = "custom-mapper")
Collection<Log> logsAsCollection;
}
6. JUnit 4 (Vintage) extension
@InjectResources
JUnit 4 (Vintage) extension simplifies access to content of resources in your JUnit tests.
6.1. Dependency
Add inject-resources-core
and inject-resources-junit-vintage
dependencies to your project.
Using Maven:
<dependency>
<groupId>io.hosuaby</groupId>
<artifactId>inject-resources-core</artifactId>
<version>0.2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.hosuaby</groupId>
<artifactId>inject-resources-junit-vintage</artifactId>
<version>0.2.2</version>
<scope>test</scope>
</dependency>
Or using Gradle:
testCompile group: 'io.hosuaby', name: 'inject-resources-core', version: '0.2.2'
testCompile group: 'io.hosuaby', name: 'inject-resources-junit-vintage', version: '0.2.2'
6.2. Resource rules
This library inject-resources-junit-vintage
provides set of rules that simplify access to content of resources. Those rules
are accessible through static method GivenResource.givenResource()
. It’s recommended to statically import this method
in test classes and use it as chained builder for resource rules.
import static com.adelean.inject.resources.junit.vintage.GivenResource.givenResource;
Then resource rules can be built using chained builder:
@Rule
public JsonResource<Person> spongeBob = givenResource()
.json("/com/adelean/junit/jupiter/sponge-bob.json")
.withCharset(StandardCharsets.UTF_8)
.parseWith(new ObjectMapper());
Following subsections show rules for different types of resources.
6.2.1. Binary resource rule
BinaryResource
rule loads content of binary resource.
Given a resource /com/adelean/junit/jupiter/fibonacci.bin
with binary content:
1 1 2 3 5 8 13 21 34 55 89
Its content can be accessed as following:
class MyTestClass {
@Rule
public BinaryResource fibonacci = givenResource()
.binary("/com/adelean/junit/jupiter/fibonacci.bin");
@Test
public void testWithBinaryResource() {
assertThat(fibonacci.get())
.contains(1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89);
}
}
6.2.2. Text resource rule
TextResource
loads content of text resource.
Assuming there is a resource /com/adelean/junit/jupiter/resource.txt
containing
The quick brown fox jumps over the lazy dog.
Its content can be accessed as following:
class MyTestClass {
@Rule
public ResourceRule<String> textResource = givenResource()
.text("/com/adelean/junit/jupiter/resource.txt")
.withCharset(StandardCharsets.UTF_8);
@Test
public void testWithTextResource() {
assertThat(textResource.get())
.isEqualTo("The quick brown fox jumps over the lazy dog.");
}
}
6.2.3. Properties resource rule
PropertiesResource
loads content of java properties resource.
Given a properties resource /com/adelean/junit/jupiter/db.properties
with content:
db.user=hosuaby
db.password=password
db.url=localhost
Its content can be accessed as following:
class MyTestClass {
@Rule
public PropertiesResource dbProperties = givenResource()
.properties("/com/adelean/junit/jupiter/db.properties");
@Test
public void testWithJavaPropertiesResource() {
assertThat(dbProperties.get())
.containsEntry("db.user", "hosuaby")
.containsEntry("db.password", "password")
.containsEntry("db.url", "localhost");
}
}
6.2.4. JSON and JSON Lines resource rules
Rules JsonResource
and JsonLinesResource
can be used to parse content of resources in formats JSON and
JSON Lines (one JSON document per line) respectively. They rely on popular libraries, Jackson or Gson to parse
content into multiple Java types like Map<String, Object>
, JsonNode
(for Jackson) & JsonElement
(for GSON) or
to Java POJO.
In order to use those rules Jackson (modules jackson-core
& jackson-databind
)
or GSON (module com.google.code.gson:gson
) must be present on
Classpath.
json()
and jsonLines()
rule builders require parser object provided using method parseWith(Object parser)
.
Example:
class MyTestClass {
/* Parse JSON with Jackson */
@Rule
public JsonResource<Map<String, Object>> jsonAsMap = givenResource()
.json("/com/adelean/junit/jupiter/sponge-bob.json")
.parseWith(new ObjectMapper());
/* Parse JSON with Gson */
@Rule
public JsonLinesResource<Collection<Log>> logsAsCollection = givenResource()
.jsonLines("/com/adelean/junit/jupiter/logs.jsonl")
.parseWith(new Gson());
}
6.2.5. YAML and YAML documents resource rules
Rules YamlResource
and YamlDocumentsResource
can be used to parse content of resources in formats YAML and
YAML documents (multiple YAML documents in the same file separated by three hyphens ---). org.yaml:snakeyaml
must be
present on Classpath in order to use those rules.
yaml()
and yamlDocument()
rule builders requires to specify org.yaml.snakeyaml.Yaml
(Snakeyaml) parser object using method
parseWith(Yaml yaml)
.
Example:
class MyTestClass {
/* Load and parse YAML resource */
@Rule
public YamlResource<Person> spongeBob = givenResource()
.yaml("/com/adelean/junit/jupiter/sponge-bob.yaml")
.parseWith(new Yaml());
/* Load and parse YAML documents resource */
@Rule
public YamlDocumentsResource<Log[]> logsAsArray = givenResource()
.yamlDocuments("/com/adelean/junit/jupiter/logs.yml")
.parseWith(new Yaml(new Constructor(Log.class)));
}