Spring Boot integration testing with JUnit - spring-boot

package com.example.demo;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
System.out.println("Hello !");
// SpringApplication.run(DemoApplication.class, args);
SpringApplication application = new SpringApplication(DemoApplication.class);
application.setBannerMode(Banner.Mode.OFF);
application.run(args);
}
}
And test
package com.example.demo;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
#SpringBootTest(classes = DemoApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class DemoApplicationTests {
#Test
void contextLoads() {
}
}
DemoApplicationTest seems to not use or be aware anythig about DemoApplication (#Spring BootApplication).
And I can't figure out if Maven project has multiple maven modules, how can they be included in test. Seem to me that Spring app does not even care about profiles defined in test.
Please point to relevant example or documentation: how to configure the test, so that it works like Spring Boot service where running on its own.
CommandLineRunner however gets executed also when running from test class:
#SpringBootApplication
public class DemoApplication implements CommandLineRunner {
public static void main(String[] args) {
System.out.println("Hello !");
// SpringApplication.run(DemoApplication.class, args);
SpringApplication application = new SpringApplication(DemoApplication.class);
application.setBannerMode(Banner.Mode.OFF);
application.run(args);
}
#Autowired
ApplicationContext applicationContext;
#Override
public void run(String... args) throws Exception {
String[] beans = applicationContext.getBeanDefinitionNames();
Arrays.sort(beans);
for (String bean : beans) {
System.out.println(bean);
}
System.out.println(".............................");
}
}
But with Spring-banner .

First, add #ExtendWith(SpringExtension.class) to your test class.
Rest of the example, you can check here :
https://howtodoinjava.com/spring-boot2/testing/spring-boot-2-junit-5/

Related

How to do integration tests with ClasspathBeanDefinitionScanner in main class springboot

here's the test I created with JPA
import static org.assertj.core.api.Assertions.assertThat;
#AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
#ExtendWith(SpringExtension.class)
#DataJpaTest
public class IntegrationTest {
#Autowired
private JpaUserRepository jpaUser;
#Test
#DisplayName("Test JPA")
void given123Password_whenPasswordIsNotValid_thenIsFalse() {
Boolean teste = this.jpaUser.existsById("Bruno");
assertThat(teste).isEqualTo(true);
}
}
here`s my main class
#SpringBootApplication
public class CleanArchitectureApplication {
public static void main(String[] args) {
SpringApplication.run(CleanArchitectureApplication.class);
}
}
Success case [https://i.stack.imgur.com/APbBu.png][1]
The problem starts when I add a classPathBeanScanner in my main class
#SpringBootApplication
public class CleanArchitectureApplication {
public static void main(String[] args) {
SpringApplication.run(CleanArchitectureApplication.class);
}
#Bean
BeanFactoryPostProcessor beanFactoryPostProcessor(ApplicationContext beanRegistry) {
return beanFactory -> {
genericApplicationContext((BeanDefinitionRegistry) ((AnnotationConfigServletWebServerApplicationContext) beanRegistry).getBeanFactory());
};
}
void genericApplicationContext(BeanDefinitionRegistry beanRegistry) {
ClassPathBeanDefinitionScanner beanDefinitionScanner = new ClassPathBeanDefinitionScanner(beanRegistry);
beanDefinitionScanner.addIncludeFilter(removeModelAndEntitiesFilter());
beanDefinitionScanner.scan("com.baeldung.pattern.cleanarchitecture");
}
static TypeFilter removeModelAndEntitiesFilter() {
return (MetadataReader mr, MetadataReaderFactory mrf) -> !mr.getClassMetadata()
.getClassName()
.endsWith("Model");
}
}
Error case [https://i.stack.imgur.com/IL0Qf.png][2]
I'm trying to implement clean architecture and abstracting main class in spring boot from this article I'm reading[https://www.baeldung.com/spring-boot-clean-architecture](https://www.stackoverflow.com/). but the problem starts when I try to do the integration test and it conflicts contexts and beans after adding the classPathBeanDefinitionScanner.
I've tried setting up different test contexts and different beans.
[1]: https://i.stack.imgur.com/APbBu.png
[2]: https://i.stack.imgur.com/IL0Qf.png

ApplicationReadyEvent not listened to when declaring #ComponentScan for library package

#componentscan({"com.test.cloud"})
#SpringBootApplication
public class TestClass {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(TestClass.class, args);
}
}
public class TestClass2{
#eventlistener(ApplicationReadyEvent.class)
public void testMethod() {
.....
.....
}
}
Here if I remove #componentscan({"com.test.cloud"}) annotation then the testMethod is triggered. But when I use #componentscan({"com.test.cloud"}) then the testMethod is not triggered.
SpringBoot Version: 1.5.10.RELEASE
Worked by adding:
#componentscan({"com.test.cloud","com.example.demo"})

Cannot correctly load application.yaml from SpringBoot/JUnit

I am a newbie with SpringBoot and I am trying to develop a first application.
My application has a configuration that is provided in an application.yaml. Currently, it successfully reads its configuration at startup.
However, if I embed my application in a Springboot/JUnit test, the application.yaml is not correctly exploited.
My impression is that, using Springboot/JUnit, application.yaml is
read as if it was an application.properties: it only accepts
parameters that are provided on a single line (e.g. thread-pool: 10)
but not on a multi-line
wordpress:
themes:
default-folder: /wp-content/themes/mkyong
I reproduced the same issue from a project I found in github: https://github.com/mkyong/spring-boot.git, in the directory yaml-simple
the application successfully reads its configuration:
#SpringBootApplication
public class Application implements CommandLineRunner {
#Autowired
private WordpressProperties wpProperties;
#Autowired
private GlobalProperties globalProperties;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
public void run(String... args) {
System.out.println(globalProperties);
System.out.println(wpProperties);
}
}
But if I create the following JUnit test in the directory
src/test/java/com/mkyong
#RunWith(SpringRunner.class)
#TestPropertySource(locations="classpath:application.yml")
public class MyTest {
#Autowired
private WordpressProperties wpProperties;
#Autowired
private GlobalProperties globalProperties;
#Test
public void myTest() {
Assert.assertTrue(globalProperties.getThreadPool() == 10); /// OK
Assert.assertEquals("/wp-content/themes/mkyong", wpProperties.getThemes().getDefaultFolder()); // KO
}
#SpringBootApplication
static class TestConfiguration {
}
}
while running it, the configuration is only partially read!!!
(please note that my problem does not appear using application.properties but I prefer yaml against properties)
Thanks the answer of user7294900, I found that adding the annotation #ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class) to my test class solved the problem:
#RunWith(SpringRunner.class)
#TestPropertySource(locations="classpath:application.yml")
#ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class)
public class MyTest {
#Autowired
private WordpressProperties wpProperties;
#Autowired
private GlobalProperties globalProperties;
#Test
public void myTest() {
Assert.assertTrue(globalProperties.getThreadPool() == 10);
Assert.assertEquals("/wp-content/themes/mkyong", wpProperties.getThemes().getDefaultFolder());
}
#SpringBootApplication
static class TestConfiguration {
}
}

#SpringbootApplication does not scan components in default package

Hi I have my main class of spring boot app in package com
and two other beans defined in com.bbh.fx.pack1.
As per my understanding SpringBootApplication will autoscan all the components in its pakacge and childern package. But it is not scanning. Not sure what i am missing
**package com.bbh.fx.pack1;**
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
#Component
public class BeanA {
#PostConstruct
public void init() {
System.out.println("in BEANA");
}
}
**package com;**
#SpringBootApplication
public class MainApp{
public static void main(String[] args) {
SpringApplication.run(MainApp.class, args);
}
}
You do not have a main in your MainApp your code should look like:
#SpringBootApplication
public class MainApp{
public static void main(String[] args) {
SpringApplication.run(MainApp.class, args);
}
}
I usually like to start all new applications from https://start.spring.io/ you can choose your project name, build type (maven or gradle) and select any spring dependencies you'd like included in the application.
Use #ComponentScan to scan components.
#SpringBootApplication
#ComponentScan("com")
public class MainApp{
public static void main(String[] args) {
SpringApplication.run(MainApp.class, args);
}
}

JUnit Platform Launcher start TestClass with Injected Spring Beans

I try to run a testclass with the JUnit Platform Launcher. The Testclass contains some #Autowired Components. The issue is, that the injection doesn't seem to work. Is that even possible with JUnit Platform?
My code is as follows:
App.java
#SpringBootApplication(scanBasePackages = "com.mytests")
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
Component
import org.springframework.stereotype.Component;
#Component
public class SomeBean {
public String returnSuccess() {
return "SUCCESS";
}
}
Testclass
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
#RunWith(SpringRunner.class)
#SpringBootTest
public class SomeTests {
#Autowired
private SomeBean aBean;
#Test
public void testSuccess() throws Exception {
String result = aBean.returnSuccess();
assertTrue(result.equals("SUCCESS"));
}
}
Controller which calls the test class
#RestController
public class TestController {
#RequestMapping("/tests")
public void executeTests() throws Throwable {
LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
.selectors(selectPackage("com.mytests"), selectClass(SomeTests.class))
.build();
Launcher launcher = LauncherFactory.create();
SummaryGeneratingListener listener = new SummaryGeneratingListener();
launcher.registerTestExecutionListeners(listener);
launcher.execute(request);
listener.getSummary();
}
}

Resources