Why is a bean created twice in test when using @PostConstruct?

823 Views Asked by At

I have a configuration class that uses a properties file and it works properly. Now I want to test that code and I have to recognize that the method annotated with @PostConstruct is run twice during the test. (In debug mode I can see that the for-loop is conducted twice.)

The configuration class:

@Slf4j
@RequiredArgsConstructor
@Configuration
@ConfigurationPropertiesScan("com.foo.bar")
public class MyConfig {

    private final MyProperties myProperties;

    @Autowired
    private GenericApplicationContext applicationContext;

    @PostConstruct
    void init() {
        Objects.requireNonNull(myProperties, "myProperties may not be null");
        for (final MyProperties.MyNestedProperty nested : myProperties.getApps()) {
            log.info("xxx {} created.", nested.getName());
            applicationContext.registerBean(nested.getName(), MyContributor.class, nested);
        }
    }
}

The used properties class:

@Slf4j
@Data
@Validated
@ConfigurationProperties(prefix = MyProperties.CONFIG_PREFIX)
public class MyProperties {

    public static final String CONFIG_PREFIX = "xxx";

    @Valid
    @NestedConfigurationProperty
    private List<MyNestedProperty> apps;

    @Data
    public static class MyNestedProperty {
        @NotNull
        @NotEmpty
        private String abc;

        private String xyzzy;

        @NotNull
        @NotEmpty
        private String name;
    }
}

My attempt with the test class:

@ExtendWith(SpringExtension.class)
@RequiredArgsConstructor
@ContextConfiguration(classes = MyConfigTest.MyTestConfiguration.class)
class MyConfigTest {
    @MockBean
    MyProperties myProperties;

    ApplicationContextRunner context;

    @BeforeEach
    void init() {
        context = new ApplicationContextRunner()
            .withBean(MyProperties.class)
            .withUserConfiguration(MyConfig.class)
        ;
    }

    @Test
    void should_check_presence_of_myConfig() {

        context.run(it -> {
            assertThat(it).hasSingleBean(MyConfig.class);
        });
    }

//    @Configuration
    @SpringBootConfiguration
//    @TestConfiguration
    static class MyTestConfiguration {
        @Bean
        MyProperties myProperties() {
            MyProperties myProperties = new MyProperties();
            MyProperties.MyNestedProperty nested = new MyProperties.MyNestedProperty();
            nested.setName("xxx");
            nested.setAbc("abc");
            nested.setXyz("xyz");
            myProperties.setApps(List.of(nested));
            return myProperties;
        }
    }
}

Why does this happen and how can I prevent this behaviour?

0

There are 0 best solutions below