Search code examples
javajunitmicronaut

How to set a @Value in a MicronautTest?


I am using Micronaut as framework for developing an AWS Java Lambda.

Micronaut supports @Value for reading, well, "values".

@io.micronaut.context.annotation.Factory
public class SomeFactory {
  public SomeFactory(
    @io.micronaut.context.annotation.Value("${NameOfValue}") 
    final String value) {
    ...
  }
  ...
}

When testing, I want to set "NameOfValue" to a specific value, how can I do that?

@io.micronaut.test.annotation.MicronautTest
class SomeLambdaIT {

  @org.junit.jupiter.api.Test
  void aTest() {
    // When this test runs, "NameOfValue" shall be set to a specific value
  }
}

Solution

  • When testing, I want to set "NameOfValue" to a specific value, how can I do that?

    You have a number of options.

    One option is to define src/test/resources/application-test.yml and define the config setting there. That file will only be loaded in the test environment and any settings defined in that file will supersede values defined in src/main/resources/application.yml.

    Another option that might make sense if you only want the special setting in play for this particular test is you can do something like this...

    import io.micronaut.test.annotation.MicronautTest;
    import org.junit.jupiter.api.Test;
    
    
    @MicronautTest(propertySources = "classpath:some-special-test-props.properties")
    public class SomeTest {
    
        @Test
        void someTest() {
            // ...
        }
    }
    

    Then define src/test/resources/some-special-test-props.properties and assign the value there.

    Yet another option is to mark your test with @Property:

    import io.micronaut.context.annotation.Property;
    import io.micronaut.test.annotation.MicronautTest;
    import org.junit.jupiter.api.Test;
    
    @MicronautTest
    @Property(name="some.config.value", value = "My Test Value")
    public class SomeTest {
    
    
        @Test
        void someTest() {
            // ...
        }
    }
    

    I hope that helps.

    EDIT

    A comment below includes "I did give it a try, but the @Property solution nor the some-special-test-props.properties works in my case.". I have created a sample app demonstrating each of these techniques. See the project at https://github.com/jeffbrown/markusschultevalue.

    https://github.com/jeffbrown/markusschultevalue/blob/8131e96492356180e2c7fade09603bd41f8c8829/src/main/java/markusschultevalue/SomeWidget.java

    package markusschultevalue;
    
    public class SomeWidget {
        private final String name;
    
        public SomeWidget(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    }
    

    https://github.com/jeffbrown/markusschultevalue/blob/master/src/main/java/markusschultevalue/SomeFactory.java

    package markusschultevalue;
    
    import io.micronaut.context.annotation.Bean;
    import io.micronaut.context.annotation.Factory;
    import io.micronaut.context.annotation.Value;
    
    @Factory
    public class SomeFactory {
    
        private final String name;
    
        // there are better ways to do this but
        // this is consistent with the code in the
        // question being asked...
        public SomeFactory(@Value("${some.config.value}") String name) {
            this.name = name;
        }
    
        @Bean
        public SomeWidget createWidget() {
            return new SomeWidget(name);
        }
    }
    

    https://github.com/jeffbrown/markusschultevalue/blob/8131e96492356180e2c7fade09603bd41f8c8829/src/test/java/markusschultevalue/PropertyAnnotationTest.java

    package markusschultevalue;
    
    import io.micronaut.context.annotation.Property;
    import io.micronaut.test.annotation.MicronautTest;
    import org.junit.jupiter.api.Test;
    
    import javax.inject.Inject;
    
    import static org.junit.jupiter.api.Assertions.assertEquals;
    
    @MicronautTest
    @Property(name="some.config.value", value="Some Widget Name")
    public class PropertyAnnotationTest {
    
        @Inject
        SomeWidget someWidget;
    
        @Test
        void testWidget() {
            assertEquals("Some Widget Name", someWidget.getName());
        }
    }
    

    https://github.com/jeffbrown/markusschultevalue/blob/8131e96492356180e2c7fade09603bd41f8c8829/src/test/java/markusschultevalue/ConfigFileTest.java

    package markusschultevalue;
    
    import io.micronaut.test.annotation.MicronautTest;
    import org.junit.jupiter.api.Test;
    
    import javax.inject.Inject;
    
    import static org.junit.jupiter.api.Assertions.assertEquals;
    
    // This will load the config value
    // from src/test/resources/some-widget-test-config.yml
    @MicronautTest(propertySources = "classpath:some-widget-test-config.yml")
    public class ConfigFileTest {
    
        @Inject
        SomeWidget someWidget;
    
        @Test
        void testWidget() {
            assertEquals("Some Other Widget Name", someWidget.getName());
        }
    }
    

    https://github.com/jeffbrown/markusschultevalue/blob/8131e96492356180e2c7fade09603bd41f8c8829/src/test/resources/some-widget-test-config.yml

    some:
      config:
        value: Some Other Widget Name
    

    Note that in your example you are referencing a config variable with "${NameOfValue}". If that is actually the name of your config variable, note that in code you need to reference that in valid kebab-case which would be "${name-of-value}".

    I hope that helps.