FINERACT-1532: Create an example for pluggability

This commit is contained in:
Aleksandar Vidakovic
2022-03-25 08:56:59 +01:00
committed by Aleksandar Vidakovic
parent 2ebde6d080
commit 83eb0842dc
60 changed files with 1354 additions and 105 deletions
@@ -22,7 +22,6 @@ import static org.mockito.Mockito.mock;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
import org.apache.fineract.infrastructure.core.boot.AbstractApplicationConfiguration;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.service.database.DatabaseIndependentQueryService;
@@ -37,19 +36,37 @@ import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* Spring @Configuration which does not require a running database. It also does not load any job configuration (as they
* are in the DB), thus nor starts any background jobs. For some integration tests, this may be perfectly sufficient
* (and faster to run such tests).
*/
@EnableConfigurationProperties({ FineractProperties.class })
@Configuration
@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class, GsonAutoConfiguration.class, JdbcTemplateAutoConfiguration.class,
LiquibaseAutoConfiguration.class })
@EnableTransactionManagement
@EnableWebSecurity
@EnableConfigurationProperties({ FineractProperties.class, LiquibaseProperties.class })
@ComponentScan(basePackages = "org.apache.fineract")
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class TestConfiguration extends AbstractApplicationConfiguration {
public class TestConfiguration {
@Bean
public TenantDataSourceFactory tenantDataSourceFactory() {
@@ -0,0 +1,54 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.module.example;
import static org.assertj.core.api.Assertions.assertThat;
import io.cucumber.java8.En;
import org.apache.fineract.dummy.core.data.DummyMessage;
import org.apache.fineract.dummy.core.service.DummyService;
import org.apache.fineract.dummy.starter.DummyAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
public class DummyServiceStepDefinitions implements En {
private DummyMessage message;
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(DummyAutoConfiguration.class));
public DummyServiceStepDefinitions() {
Given("/^A dummy service configuration (.*)$/", (String configurationClass) -> {
contextRunner = contextRunner.withUserConfiguration(Class.forName(configurationClass.trim()));
});
When("The user gets the dummy service message", () -> {
contextRunner.run((ctx) -> {
assertThat(ctx).hasSingleBean(DummyService.class);
this.message = ctx.getBean(DummyService.class).getMessage();
});
});
Then("/^The dummy service message should match (.*)$/", (String msg) -> {
assertThat(this.message).isNotNull();
assertThat(msg).isEqualTo(this.message.getMessage());
});
}
}
@@ -0,0 +1,25 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.module.example;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@EnableConfigurationProperties({ FineractProperties.class })
public class TestDefaultConfiguration {}
@@ -0,0 +1,27 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.module.example;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.ComponentScan;
@EnableConfigurationProperties({ FineractProperties.class })
@ComponentScan("com.acmecorp.fineract.foo")
public class TestFooConfiguration {}
@@ -0,0 +1,58 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.module.service;
import static org.assertj.core.api.Assertions.assertThat;
import io.cucumber.java8.En;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
public class ServiceStepDefinitions implements En {
private Class interfaceClass;
private Class implementationClass;
private ApplicationContextRunner contextRunner;
public ServiceStepDefinitions() {
Given("/^An auto configuration (.*) and a service configuration (.*)$/",
(String autoConfigurationClassName, String configurationClassName) -> {
contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(Class.forName(autoConfigurationClassName)))
.withUserConfiguration(Class.forName(configurationClassName.trim()));
});
When("/^The user retrieves the service of interface class (.*)$/", (String interfaceClassName) -> {
contextRunner.run((ctx) -> {
this.interfaceClass = Class.forName(interfaceClassName.trim());
assertThat(this.interfaceClass.isInterface()).isTrue();
assertThat(ctx).hasSingleBean(this.interfaceClass);
this.implementationClass = ctx.getBean(interfaceClass).getClass();
});
});
Then("/^The service class should match (.*)$/", (String serviceClassName) -> {
assertThat(Class.forName(serviceClassName.trim())).isEqualTo(this.implementationClass);
});
}
}
@@ -0,0 +1,84 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.module.service;
import static org.mockito.Mockito.mock;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
import org.apache.fineract.infrastructure.core.service.RoutingDataSourceServiceFactory;
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
import org.apache.fineract.portfolio.group.domain.GroupRepository;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
import org.apache.fineract.portfolio.note.domain.NoteRepository;
import org.apache.fineract.portfolio.note.serialization.NoteCommandFromApiJsonDeserializer;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
@EnableConfigurationProperties({ FineractProperties.class })
public class TestDefaultConfiguration {
// NOTE: unfortunately an abastract base class that contains all these mock functions won't work
@Bean
public FromJsonHelper fromJsonHelper() {
return mock(FromJsonHelper.class);
}
@Bean
public RoutingDataSourceServiceFactory routingDataSourceServiceFactory() {
return mock(RoutingDataSourceServiceFactory.class);
}
@Bean
public RoutingDataSource routingDataSource() {
return mock(RoutingDataSource.class);
}
@Bean
public NoteRepository noteRepository() {
return mock(NoteRepository.class);
}
@Bean
public ClientRepositoryWrapper clientRepository() {
return mock(ClientRepositoryWrapper.class);
}
@Bean
public GroupRepository groupRepository() {
return mock(GroupRepository.class);
}
@Bean
public LoanRepositoryWrapper loanRepository() {
return mock(LoanRepositoryWrapper.class);
}
@Bean
public LoanTransactionRepository loanTransactionRepository() {
return mock(LoanTransactionRepository.class);
}
@Bean
public NoteCommandFromApiJsonDeserializer fromApiJsonDeserializer(FromJsonHelper fromJsonHelper) {
return new NoteCommandFromApiJsonDeserializer(fromJsonHelper);
}
}
@@ -0,0 +1,83 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.module.service;
import static org.mockito.Mockito.mock;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
import org.apache.fineract.infrastructure.core.service.RoutingDataSourceServiceFactory;
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
import org.apache.fineract.portfolio.group.domain.GroupRepository;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
import org.apache.fineract.portfolio.note.domain.NoteRepository;
import org.apache.fineract.portfolio.note.serialization.NoteCommandFromApiJsonDeserializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan("org.apache.fineract.module.service.custom")
public class TestOverrideConfiguration {
// NOTE: unfortunately an abastract base class that contains all these mock functions won't work
@Bean
public FromJsonHelper fromJsonHelper() {
return mock(FromJsonHelper.class);
}
@Bean
public RoutingDataSourceServiceFactory routingDataSourceServiceFactory() {
return mock(RoutingDataSourceServiceFactory.class);
}
@Bean
public RoutingDataSource routingDataSource() {
return mock(RoutingDataSource.class);
}
@Bean
public NoteRepository noteRepository() {
return mock(NoteRepository.class);
}
@Bean
public ClientRepositoryWrapper clientRepository() {
return mock(ClientRepositoryWrapper.class);
}
@Bean
public GroupRepository groupRepository() {
return mock(GroupRepository.class);
}
@Bean
public LoanRepositoryWrapper loanRepository() {
return mock(LoanRepositoryWrapper.class);
}
@Bean
public LoanTransactionRepository loanTransactionRepository() {
return mock(LoanTransactionRepository.class);
}
@Bean
public NoteCommandFromApiJsonDeserializer fromApiJsonDeserializer(FromJsonHelper fromJsonHelper) {
return new NoteCommandFromApiJsonDeserializer(fromJsonHelper);
}
}
@@ -0,0 +1,38 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.module.service.custom;
import java.util.Collection;
import org.apache.fineract.portfolio.note.data.NoteData;
import org.apache.fineract.portfolio.note.service.NoteReadPlatformService;
import org.springframework.stereotype.Service;
@Service
public class CustomNoteReadPlatformService implements NoteReadPlatformService {
@Override
public NoteData retrieveNote(Long noteId, Long resourceId, Integer noteTypeId) {
return null;
}
@Override
public Collection<NoteData> retrieveNotesByResource(Long resourceId, Integer noteTypeId) {
return null;
}
}
@@ -0,0 +1,49 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.module.service.custom;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.note.service.NoteWritePlatformService;
import org.springframework.stereotype.Service;
@Service
public class CustomNoteWritePlatformService implements NoteWritePlatformService {
@Override
public CommandProcessingResult createNote(JsonCommand command) {
return null;
}
@Override
public CommandProcessingResult updateNote(JsonCommand command) {
return null;
}
@Override
public CommandProcessingResult deleteNote(JsonCommand command) {
return null;
}
@Override
public void createAndPersistClientNote(Client client, JsonCommand command) {
}
}