Search code examples
springspring-boottestingjavabeans

how to conditionally not create beans in spring boot?


In my application, I have a component that reads data from other system when the application is started. However, during testing, I don't want this component to be created

@Component
@Slf4j
public class DeviceStatisticsSyncHandler {
    @EventListener
    public void handle(ApplicationReadyEvent event) {
        syncDeviceStatisticsDataSync();
    }

    @Value("${test.mode:false}")
    public  boolean serviceEnabled;
}

I can use condition to solve this, but other code readers need to understand, so I don't think this is a very good method:

@EventListener(condition =  "@deviceStatisticsSyncHandler .isServiceEnabled()")
public void handle(ApplicationReadyEvent event) {
    syncDeviceStatisticsDataSync();
}

public  boolean isServiceEnabled() {
    return !serviceEnabled;
}

@Value("${test.mode:false}")
public  boolean serviceEnabled;

My application doesn't use Profiles, is there any other method to solve this problem.

Spring Boot version:2.1.3


Solution

  • One possible option is not to load the DeviceStaticsticsSyncHandler at all if you're in a test mode. The "test.mode" is not a good name here, because the production code contains something tightly bound to the tests.

    How about the following approach:

    @Component
    @ConditionalOnProperty(name ="device.stats.handler.enabled", havingValue = "true", matchIfMissing=true) 
    public class DeviceStatisticsSyncHandler {
       // do whatever you need here, but there is no need for "test.mode" enabled related code here
    }
    

    Now in Tests you can define a test property "device.stats.handler.enabled=false" on the test itself or even place that definition in src/test/reources/application.properties so it will be false for all tests in the module.

    An obvious advantage is that this definition is pretty much self explanatory and can be easy understood by other project maintainers.