BBL - @InjectResources - Adelean
github.com/hosuaby/inject-resourcesImporter le contenu d'une ressource en Java est plus compliqué que ça ne devrais être.
Lécture d'une ressource (Java pure)
String resourcePath = "com/adelean/junit/jupiter/resource.txt";
ClassLoader classLoader = getClass().getClassLoader();
StringBuilder textBuilder = new StringBuilder();
try (InputStream resourceAsStream = classLoader.getResourceAsStream(resourcePath);
InputStreamReader streamReader = new InputStreamReader(resourceAsStream);
BufferedReader bufferedReader = new BufferedReader(streamReader)) {
int c = 0;
while ((c = bufferedReader.read()) != -1) {
textBuilder.append((char) c);
}
} catch (IOException ioException) {
// handle exception
}
String resourceContent = textBuilder.toString();
// resourceContent == "The quick brown fox jumps over the lazy dog."
Lécture d'une ressource (Guava)
URL url = Resources.getResource("com/adelean/junit/jupiter/resource.txt");
try {
String resourceContent = Resources.toString(url, StandardCharsets.UTF_8);
} catch (IOException ioException) {
// handle exception
}
- Ressource ≠ fichier
- Ressource ≈ import
Vous ne faitez pas ça, n'est ce pas ?
try {
import java.util.ArrayList;
} catch (IOException ioException) {
// handle exception
}
Peut-on faire plus simple ?
Avec @InjectResources
Contenu de /com/adelean/junit/jupiter/resource.txt:
The quick brown fox jumps over the lazy dog.
@TestWithResources // <-- ajouter l'extention
class InjectTextResourcesTests {
@GivenTextResource("/com/adelean/junit/jupiter/resource.txt")
String resourceContent; // <-- injecter le contenu de la resource
@Test
public void testInjectTextIntoStringInstanceField() {
assertThat(resourceContent)
.isEqualTo("The quick brown fox jumps over the lazy dog.");
}
}
Contenu de /com/adelean/junit/jupiter/fibonacci.bin (binaire):
1 1 2 3 5 8 13 21 34 55 89
@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);
}
}
Contenu de /com/adelean/junit/jupiter/db.properties:
db.user=hosuaby
db.password=password
db.url=localhost
@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");
}
}
Injecter contenu JSON avec Jackson
@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;
}
Example avec un test de A2
@TestWithResources
class CatalogConfigTest {
@WithJacksonMapper
ObjectMapper objectMapper = JacksonUtils.objectMapper();
@Test
void testGetUsedGlobalSynonyms(
@GivenJsonResource("com/adelean/a2/model/config/v2_frontal_648.config.json")
CatalogConfig catalogConfig) {
SynonymDictionary dictionary = catalogConfig.getAllSynonyms();
assertTrue(dictionary.areSynonyms("rasage", "raser"));
assertTrue(dictionary.areSynonyms("raser", "rasage"));
}
}
Parseur partagé par plusiers classes des tests (héritage)
abstract class SuperClassWithParser {
@WithJacksonMapper
ObjectMapper objectMapper = new ObjectMapper()
.registerModule(new JavaTimeModule());
}
@TestWithResources
class TestsSubclass1 extends SuperClassWithParser {
@GivenJsonLinesResource(from = "/com/adelean/junit/jupiter/logs.jsonl")
Collection< Log > logsAsCollection;
}
@TestWithResources
class TestsSubclass2 extends SuperClassWithParser {
@GivenJsonResource("com/adelean/a2/model/config/v2_frontal_648.config.json")
CatalogConfig catalog648Config;
}
Parseur partagé par plusiers classes des tests (Tests Advice)
@TestsAdvice
public final class GlobalObjectMapperProvider {
@WithJacksonMapper
public ObjectMapper globalObjectMapper() {
return JacksonUtils.objectMapper();
}
}
Parseurs nommés
@TestWithResources
class TestsWithNamedParser {
@WithJacksonMapper("custom-mapper")
ObjectMapper objectMapper = new ObjectMapper()
.registerModule(new JavaTimeModule());
@GivenJsonLinesResource(
from = "/com/adelean/junit/jupiter/logs.jsonl",
jacksonMapper = "custom-mapper")
Collection< Log > logsAsCollection;
}
Parsing des properties dans POJO avec jackson-dataformat-properties
class JavaDslTests {
JavaPropsSchema SCHEMA = JavaPropsSchema
.emptySchema()
.withoutPathSeparator();
ObjectReader READER = new JavaPropsMapper()
.readerFor(DbConnection.class)
.with(SCHEMA);
String PATH_PREFIX = "/com/adelean/junit/jupiter";
static class DbConnection {
@JsonProperty("db.user") String user;
@JsonProperty("db.password") String password;
@JsonProperty("db.url") String url;
}
@Test
public void testResourceAsStream() {
// @InjectResources Java DSL
var dbConnection = resource()
.withPath(PATH_PREFIX, "db.properties")
.asInputStream()
.parseChecked(READER::readValue);
assertThat(dbConnection)
.isNotNull()
.hasFieldOrPropertyWithValue("user", "hosuaby")
.hasFieldOrPropertyWithValue("password", "password")
.hasFieldOrPropertyWithValue("url", "localhost");
}
}
A venir:
- Support XML (probablement JAX-B)
- Support YAML avec SnakeYAML
- Extension JUnit 4
- Caching pour le resources parsés
La fin :)
(Merci pour votre attention!)
P.S. N'oubliez pas à visiter:
github.com/hosuaby/inject-resources