I have a spring-boot app that now needs to support multiple Object stores and selectively use the desired store based on the environment. Essentially what i have done is create an interface that each store repository then implements.
I have simplified the code for the examples. I have created 2 beans for each store type based on the spring profile determining the env:
@Profile("env1")
@Bean
public store1Sdk buildClientStore1() {
return new store1sdk();
}
@Profile("env2")
@Bean
public store2Sdk buildClientStore2() {
return new store2sdk();
}
in the service layer I have autowired the interface and then in the repositories i have used @Profile to specify which instance of the interface to use.
public interface ObjectStore {
String download(String fileObjectKey);
...
}
@Service
public class ObjectHandlerService {
@Autowired
private ObjectStore objectStore;
public String getObject(String fileObjectKey) {
return objectStore.download(fileObjectKey);
}
...
}
@Repository
@Profile("env1")
public class Store1Repository implements ObjectStore {
@Autowired
private Store1Sdk store1client;
public String download(String fileObjectKey) {
return store1client.getObject(storeName, fileObjectKey);
}
}
When I start the application with the configured "env" this actually runs as expected. however when running the test I get the "no qualifying bean of type ObjectStore. expected at least 1 bean which qualifies as autowire candidate."
@ExtendWith({ SpringExtension.class })
@SpringBootTest(classes = Application.class)
@ActiveProfiles("env1,test")
public class ComposerServiceTest {
@Autowired
private ObjectHandlerService service;
@Test
void download_success() {
String response = service.getObject("testKey");
...
}
}
As noted in the @ActiveProfile on the test class there are some other environments e.g. dev,test,prod. I have tried playing around with Component scan, having impl and interface in the same package, etc, to no success. I feel like I am missing something obvious with the test setup. But could be something with my overall application config? my main aim with the solution is to avoid having something a long the lines of
if (store1Sdk != null) {
store1Sdk.download(fileObjectKey);
}
if (store2Sdk != null) {
store2Sdk.download(fileObjectKey);
}
Try @ActiveProfiles({"env1", "test"})
.
Activate multiple profiles using @ActiveProfiles
and specify profiles as an array.