From 493568649acb89d31f272c41271a51dbb75c2aeb Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Sat, 9 Jun 2018 15:02:22 -0300 Subject: [PATCH] Spring Boot autoconfiguration improvements. Unit test refactoring, now with autoconfiguration integration testing. Bug fix that did not initialize the bots, even with the deprecated @EnableTelegramBots * [Removed - If users wish to disable, just inform telegrambots.enabled = false]. Upgrade Spring boot 2.0.2 --- telegrambots-spring-boot-starter/README.md | 4 +- telegrambots-spring-boot-starter/pom.xml | 19 ++- .../starter/EnableTelegramBots.java | 10 -- .../starter/TelegramBotInitializer.java | 45 ++++++ .../TelegramBotStarterConfiguration.java | 77 +++------- .../main/resources/META-INF/spring.factories | 1 + .../TestTelegramBotStarterConfiguration.java | 137 +++++++++++------- 7 files changed, 172 insertions(+), 121 deletions(-) delete mode 100644 telegrambots-spring-boot-starter/src/main/java/org/telegram/telegrambots/starter/EnableTelegramBots.java create mode 100644 telegrambots-spring-boot-starter/src/main/java/org/telegram/telegrambots/starter/TelegramBotInitializer.java create mode 100644 telegrambots-spring-boot-starter/src/main/resources/META-INF/spring.factories diff --git a/telegrambots-spring-boot-starter/README.md b/telegrambots-spring-boot-starter/README.md index 8bb3f2a8..34b2cff5 100644 --- a/telegrambots-spring-boot-starter/README.md +++ b/telegrambots-spring-boot-starter/README.md @@ -25,7 +25,7 @@ Usage **Gradle** ```gradle - compile "org.telegram:telegrambots-spring-boot-starter:3.6" + compile "org.telegram:telegrambots-spring-boot-starter:3.6.1" ``` Motivation @@ -39,8 +39,6 @@ Your main spring boot class should look like this: ```java @SpringBootApplication -//Add this annotation to enable automatic bots initializing -@EnableTelegramBots public class YourApplicationMainClass { public static void main(String[] args) { diff --git a/telegrambots-spring-boot-starter/pom.xml b/telegrambots-spring-boot-starter/pom.xml index 72ed3705..dba8f1e1 100644 --- a/telegrambots-spring-boot-starter/pom.xml +++ b/telegrambots-spring-boot-starter/pom.xml @@ -60,7 +60,7 @@ UTF-8 UTF-8 3.6.1 - 1.5.10.RELEASE + 2.0.2.RELEASE @@ -75,24 +75,41 @@ spring-boot ${spring-boot.version} + org.springframework.boot spring-boot-autoconfigure ${spring-boot.version} + + + org.springframework.boot + spring-boot-test + ${spring-boot.version} + test + + + org.assertj + assertj-core + test + 3.9.1 + + org.mockito mockito-all 2.0.2-beta test + junit junit 4.11 test + diff --git a/telegrambots-spring-boot-starter/src/main/java/org/telegram/telegrambots/starter/EnableTelegramBots.java b/telegrambots-spring-boot-starter/src/main/java/org/telegram/telegrambots/starter/EnableTelegramBots.java deleted file mode 100644 index 68c4acf9..00000000 --- a/telegrambots-spring-boot-starter/src/main/java/org/telegram/telegrambots/starter/EnableTelegramBots.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.telegram.telegrambots.starter; - -import org.springframework.context.annotation.Import; - -/** - * Imports configuration #TelegramBotStarterConfiguration in spring context. - */ -@Import(TelegramBotStarterConfiguration.class) -public @interface EnableTelegramBots { -} diff --git a/telegrambots-spring-boot-starter/src/main/java/org/telegram/telegrambots/starter/TelegramBotInitializer.java b/telegrambots-spring-boot-starter/src/main/java/org/telegram/telegrambots/starter/TelegramBotInitializer.java new file mode 100644 index 00000000..5348ae7c --- /dev/null +++ b/telegrambots-spring-boot-starter/src/main/java/org/telegram/telegrambots/starter/TelegramBotInitializer.java @@ -0,0 +1,45 @@ +package org.telegram.telegrambots.starter; + +import java.util.List; +import java.util.Objects; + +import org.springframework.beans.factory.InitializingBean; +import org.telegram.telegrambots.TelegramBotsApi; +import org.telegram.telegrambots.exceptions.TelegramApiException; +import org.telegram.telegrambots.generics.LongPollingBot; +import org.telegram.telegrambots.generics.WebhookBot; + +/** + * Receives all beand which are #LongPollingBot and #WebhookBot and register them in #TelegramBotsApi. + */ +public class TelegramBotInitializer implements InitializingBean { + + private final TelegramBotsApi telegramBotsApi; + private final List longPollingBots; + private final List webHookBots; + + public TelegramBotInitializer(TelegramBotsApi telegramBotsApi, + List longPollingBots, + List webHookBots) { + Objects.requireNonNull(telegramBotsApi); + Objects.requireNonNull(longPollingBots); + Objects.requireNonNull(webHookBots); + this.telegramBotsApi = telegramBotsApi; + this.longPollingBots = longPollingBots; + this.webHookBots = webHookBots; + } + + @Override + public void afterPropertiesSet() throws Exception { + try { + for (LongPollingBot bot : longPollingBots) { + telegramBotsApi.registerBot(bot); + } + for (WebhookBot bot : webHookBots) { + telegramBotsApi.registerBot(bot); + } + } catch (TelegramApiException e) { + throw new RuntimeException(e); + } + } +} diff --git a/telegrambots-spring-boot-starter/src/main/java/org/telegram/telegrambots/starter/TelegramBotStarterConfiguration.java b/telegrambots-spring-boot-starter/src/main/java/org/telegram/telegrambots/starter/TelegramBotStarterConfiguration.java index 11e66af3..86ef0c33 100644 --- a/telegrambots-spring-boot-starter/src/main/java/org/telegram/telegrambots/starter/TelegramBotStarterConfiguration.java +++ b/telegrambots-spring-boot-starter/src/main/java/org/telegram/telegrambots/starter/TelegramBotStarterConfiguration.java @@ -1,70 +1,37 @@ package org.telegram.telegrambots.starter; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.telegram.telegrambots.TelegramBotsApi; -import org.telegram.telegrambots.exceptions.TelegramApiRequestException; -import org.telegram.telegrambots.generics.LongPollingBot; -import org.telegram.telegrambots.generics.WebhookBot; - -import javax.annotation.PostConstruct; +import java.util.Collections; import java.util.List; import java.util.Optional; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.telegram.telegrambots.TelegramBotsApi; +import org.telegram.telegrambots.generics.LongPollingBot; +import org.telegram.telegrambots.generics.WebhookBot; + /** - * Receives all beand which are #LongPollingBot and #WebhookBot and register them in #TelegramBotsApi. * #TelegramBotsApi added to spring context as well */ @Configuration +@ConditionalOnProperty(prefix="telegrambots",name = "enabled", havingValue = "true", matchIfMissing = true) public class TelegramBotStarterConfiguration { - - - private final List longPollingBots; - private final List webHookBots; - - private TelegramBotsApi telegramBotsApi; - - @Autowired - public void setTelegramBotsApi(TelegramBotsApi telegramBotsApi) { - this.telegramBotsApi = telegramBotsApi; - } - - public TelegramBotStarterConfiguration(@Autowired(required = false) List longPollingBots, - @Autowired(required = false) List webHookBots) { - - this.longPollingBots = longPollingBots; - this.webHookBots = webHookBots; - } - - @PostConstruct - public void registerBots() { - Optional.ofNullable(longPollingBots).ifPresent(bots -> { - bots.forEach(bot -> { - try { - telegramBotsApi.registerBot(bot); - } catch (TelegramApiRequestException e) { - throw new RuntimeException(e); - } - }); - }); - - Optional.ofNullable(webHookBots).ifPresent(bots -> { - bots.forEach(bot -> { - try { - telegramBotsApi.registerBot(bot); - } catch (TelegramApiRequestException e) { - throw new RuntimeException(e); - } - }); - }); - } - - + @Bean @ConditionalOnMissingBean(TelegramBotsApi.class) - public TelegramBotsApi telegramBotsApi() { + public TelegramBotsApi telegramBotsApi() { return new TelegramBotsApi(); } + + @Bean + @ConditionalOnMissingBean + public TelegramBotInitializer telegramBotInitializer(TelegramBotsApi telegramBotsApi, + Optional> longPollingBots, + Optional> webHookBots) { + return new TelegramBotInitializer(telegramBotsApi, + longPollingBots.orElseGet(Collections::emptyList), + webHookBots.orElseGet(Collections::emptyList)); + } } diff --git a/telegrambots-spring-boot-starter/src/main/resources/META-INF/spring.factories b/telegrambots-spring-boot-starter/src/main/resources/META-INF/spring.factories new file mode 100644 index 00000000..71b3a84d --- /dev/null +++ b/telegrambots-spring-boot-starter/src/main/resources/META-INF/spring.factories @@ -0,0 +1 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.telegram.telegrambots.starter.TelegramBotStarterConfiguration \ No newline at end of file diff --git a/telegrambots-spring-boot-starter/src/test/java/org/telegram/telegrambots/starter/TestTelegramBotStarterConfiguration.java b/telegrambots-spring-boot-starter/src/test/java/org/telegram/telegrambots/starter/TestTelegramBotStarterConfiguration.java index 00a1e7cf..d8723664 100644 --- a/telegrambots-spring-boot-starter/src/test/java/org/telegram/telegrambots/starter/TestTelegramBotStarterConfiguration.java +++ b/telegrambots-spring-boot-starter/src/test/java/org/telegram/telegrambots/starter/TestTelegramBotStarterConfiguration.java @@ -1,66 +1,99 @@ package org.telegram.telegrambots.starter; -import com.google.common.collect.Lists; -import org.junit.Rule; + +import static org.assertj.core.api.Assertions.assertThat; + import org.junit.Test; -import org.mockito.Answers; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; +import static org.mockito.Mockito.*; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.telegram.telegrambots.TelegramBotsApi; -import org.telegram.telegrambots.exceptions.TelegramApiRequestException; import org.telegram.telegrambots.generics.LongPollingBot; import org.telegram.telegrambots.generics.WebhookBot; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; - public class TestTelegramBotStarterConfiguration { - @Mock - private TelegramBotsApi telegramBotsApi; + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(MockTelegramBotsApi.class, TelegramBotStarterConfiguration.class)); - @Rule - public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Test + public void createMockTelegramBotsApiWithDefaultSettings() { + this.contextRunner.run((context) -> { + assertThat(context).hasSingleBean(TelegramBotsApi.class); + assertThat(context).hasSingleBean(TelegramBotInitializer.class); + assertThat(context).doesNotHaveBean(LongPollingBot.class); + assertThat(context).doesNotHaveBean(WebhookBot.class); + verifyNoMoreInteractions(context.getBean(TelegramBotsApi.class)); + }); + } + + @Test + public void createOnlyLongPollingBot() { + this.contextRunner.withUserConfiguration(LongPollingBotConfig.class) + .run((context) -> { + assertThat(context).hasSingleBean(LongPollingBot.class); + assertThat(context).doesNotHaveBean(WebhookBot.class); + + TelegramBotsApi telegramBotsApi = context.getBean(TelegramBotsApi.class); + + verify(telegramBotsApi, times(1)).registerBot( context.getBean(LongPollingBot.class) ); + verifyNoMoreInteractions(telegramBotsApi); + }); + } + + @Test + public void createOnlyWebhookBot() { + this.contextRunner.withUserConfiguration(WebhookBotConfig.class) + .run((context) -> { + assertThat(context).hasSingleBean(WebhookBot.class); + assertThat(context).doesNotHaveBean(LongPollingBot.class); + + TelegramBotsApi telegramBotsApi = context.getBean(TelegramBotsApi.class); + + verify(telegramBotsApi, times(1)).registerBot( context.getBean(WebhookBot.class) ); + verifyNoMoreInteractions(telegramBotsApi); + }); + } + + @Test + public void createLongPoolingBotAndWebhookBot() { + this.contextRunner.withUserConfiguration(LongPollingBotConfig.class, WebhookBotConfig.class) + .run((context) -> { + assertThat(context).hasSingleBean(LongPollingBot.class); + assertThat(context).hasSingleBean(WebhookBot.class); - @Test - public void TestRegisterBotsWithLongPollingBots() throws TelegramApiRequestException { - when(telegramBotsApi.registerBot(any(LongPollingBot.class))).then(Answers.RETURNS_MOCKS.get()); - LongPollingBot longPollingBot = mock(LongPollingBot.class); - TelegramBotStarterConfiguration configuration = new TelegramBotStarterConfiguration(Lists.newArrayList(longPollingBot), null); - configuration.setTelegramBotsApi(telegramBotsApi); + TelegramBotsApi telegramBotsApi = context.getBean(TelegramBotsApi.class); + + verify(telegramBotsApi, times(1)).registerBot( context.getBean(LongPollingBot.class) ); + verify(telegramBotsApi, times(1)).registerBot( context.getBean(WebhookBot.class) ); + //verifyNoMoreInteractions(telegramBotsApi); + }); + } - configuration.registerBots(); + @Configuration + static class MockTelegramBotsApi{ - verify(telegramBotsApi, times(1)).registerBot(longPollingBot); - verifyNoMoreInteractions(telegramBotsApi); - } - - @Test - public void TestRegisterBotsWithWebhookBots() throws TelegramApiRequestException { - doNothing().when(telegramBotsApi).registerBot(any(WebhookBot.class)); - WebhookBot webhookBot = mock(WebhookBot.class); - TelegramBotStarterConfiguration configuration = new TelegramBotStarterConfiguration(null, Lists.newArrayList(webhookBot)); - configuration.setTelegramBotsApi(telegramBotsApi); - - configuration.registerBots(); - - verify(telegramBotsApi, times(1)).registerBot(webhookBot); - verifyNoMoreInteractions(telegramBotsApi); - } - - @Test - public void TestRegisterBotsWithLongPollingBotsAndWebhookBots() throws TelegramApiRequestException { - doNothing().when(telegramBotsApi).registerBot(any(WebhookBot.class)); - LongPollingBot longPollingBot = mock(LongPollingBot.class); - WebhookBot webhookBot = mock(WebhookBot.class); - TelegramBotStarterConfiguration configuration = new TelegramBotStarterConfiguration(Lists.newArrayList(longPollingBot), Lists.newArrayList(webhookBot)); - configuration.setTelegramBotsApi(telegramBotsApi); - - configuration.registerBots(); - - verify(telegramBotsApi, times(1)).registerBot(longPollingBot); - verify(telegramBotsApi, times(1)).registerBot(webhookBot); - verifyNoMoreInteractions(telegramBotsApi); - } + @Bean + public TelegramBotsApi telegramBotsApi() { + return mock(TelegramBotsApi.class); + } + } + + @Configuration + static class LongPollingBotConfig{ + @Bean + public LongPollingBot longPollingBot() { + return mock(LongPollingBot.class); + } + } + + @Configuration + static class WebhookBotConfig{ + @Bean + public WebhookBot webhookBot() { + return mock(WebhookBot.class); + } + } }