Hi there. I'm trying to test a dropwizard configuration file following the guidelines set out here: https://www.dropwizard.io/1.3.13/docs/manual/testing.html#testing-configurations
This works fine for simple configuration files, but unfortunately doesn't cater for more complex configuration files involving parameters.
For example, the following configuration will fail to parse:
Config file:
import io.dropwizard.Configuration;
import lombok.Getter;
@Getter
public class SomeConfigurationFile extends Configuration {
private long someAttribute;
}
YAML file:
server:
applicationConnectors:
- type: http
port: 1234
adminConnectors:
- type: http
port: 5678
someAttribute: ${SOME_ENV_VAR:-3000}
When attempting to run this, i get the following error:
io.dropwizard.configuration.ConfigurationParsingException: src/main/resources/config.yaml has an error:
* Incorrect type of value at: pollingFrequency; is of type: String, expected: long
at io.dropwizard.configuration.ConfigurationParsingException$Builder.build(ConfigurationParsingException.java:279)
at io.dropwizard.configuration.BaseConfigurationFactory.build(BaseConfigurationFactory.java:149)
at io.dropwizard.configuration.BaseConfigurationFactory.build(BaseConfigurationFactory.java:89)
at io.dropwizard.configuration.ConfigurationFactory.build(ConfigurationFactory.java:28)
at <myTest>.<myTestMethod>(<myTest>.java:44)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.contrib.java.lang.system.EnvironmentVariables$EnvironmentVariablesStatement.evaluate(EnvironmentVariables.java:122)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `long` from String "${someAttribute:-3000}": not a valid Long value
at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: <myConfigFile>["someAttribute"])
at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.weirdStringException(DeserializationContext.java:1549)
The reason for this is that i have no way to define a ConfigurationSourceProvider within this test. When running the full application, i can initialise this using the Application.initialize() method as follows:
bootstrap.setConfigurationSourceProvider(
new SubstitutingSourceProvider(
bootstrap.getConfigurationSourceProvider(),
new EnvironmentVariableSubstitutor(false))
);
This is not available in the test however. Does anyone know how this could be achieved?
My test class:
import com.fasterxml.jackson.databind.ObjectMapper;
import io.dropwizard.configuration.EnvironmentVariableSubstitutor;
import io.dropwizard.configuration.SubstitutingSourceProvider;
import io.dropwizard.configuration.YamlConfigurationFactory;
import io.dropwizard.jackson.Jackson;
import io.dropwizard.jersey.validation.Validators;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.testing.ResourceHelpers;
import io.dropwizard.testing.junit.DropwizardAppRule;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import javax.validation.Validator;
import java.io.File;
import static org.junit.Assert.*;
public class MyConfigurationTest {
private YamlConfigurationFactory<MyConfiguration> factory;
@Before
public void setUp() {
ObjectMapper objectMapper = Jackson.newObjectMapper();
Validator validator = Validators.newValidator();
factory = new YamlConfigurationFactory<>(MyConfiguration.class, validator, objectMapper, "dw");
}
@Test
public void testAppConfigurationIsValid() throws Exception {
File yaml = new File("src/main/resources/config.yaml");
final MyConfiguration config = factory.build(yaml);
assertNotNull(config);
}
}
Did you know about / try:
factory.build(
new SubstitutingSourceProvider(
new ResourceConfigurationSourceProvider(),
new EnvironmentVariableSubstitutor(false)
), "config.yaml");
or is it not applicable?
Did you know about / try:
factory.build( new SubstitutingSourceProvider( new ResourceConfigurationSourceProvider(), new EnvironmentVariableSubstitutor(false) ), "config.yaml");or is it not applicable?
This actually works FLAWLESSLY :D Thanks very much!
In all my trawling of the documentation, this is something I didn't stumble upon. May be worth adding this to the documentation under the section for testing configurations.
@jamesalfei Would you mind creating a PR to add this to the documentation?
@joschi Sure thing, I'll get that up over the next couple of days.
I've opened PR https://github.com/dropwizard/dropwizard/pull/2874 for this. I'll close this ticket now and any conversation can now take place on the PR. Thanks for the help all!
Most helpful comment
Did you know about / try:
or is it not applicable?