SpringBootTest annotation in test classes - java

I had an error during my jUnit test after adding a second test class.
java.lang.IllegalStateException: Unable to find a #SpringBootConfiguration, you need to use #ContextConfiguration or #SpringBootTest(classes=...) with your test
...so I added (classes=...) part to the SpringBootTest annotation, and tests run fine.
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {mySecondJUnitClass.class})
public class mySecondJUnitClass{
What I didn't understand is, I didn't add that "classes" to my first test class, I only set #SpringBootTest annotation and worked fine.
#RunWith(SpringRunner.class)
#SpringBootTest
public class myFirstJUnitClass{
When and why do we need that "classes" definition? Why is not #SpringBootTest not enough?

I found the answer (by the help of JB Nizet). My first test class was in the subpackage of the package of my main class and the second was not. So this was why it needed a classes definition.

Related

Adding `#SpringBootTest` annotation triggers IntelliJ false positives

So If you have a test class
class FooControllerIT{
#Autowired FooController controller;
}
and you add an #SpringBootTest annotation to the class, IntelliJ claims that
Could not autowire. No beans of 'FooController' type found.
Which is a lie because the tests run and pass just fine.
If I replace the #SpringBootTest annotation with, say, an #Component annotation, the "error" disappears (and re-appears when I substitute the #SpringBootTest annotation back in again).
What causes this behaviour?
(I'm on ultimate 2019.1, using Spring Boot 2.1.8-RELEASE)
The possible way that your Controller cannot be found is that it is not in the same (or higher) package as your main application class annotated #SpringBootApplication. If you don't want to move the Controller, you can create a new configuration class that will be annotated as #ComponentScan
#Configuration
#ComponentScan(basePackages = "com.your.controller.package")
public class FooConfig {
}
Even that you can add this config manually to your test spring context: #SpringBootTest(classes = FooConfig.class)

#SpringBootTest annotation giving Failed to load ApplicationContext Error

New to spring. I am trying to upgrade spring-boot-starter-parent from v1.3.2 to the latest v2.1.4. Made the POM file change for version upgrade. I have made all the necessary code changes to solve the compilation problems. when I am trying to run the test cases though, Test Classes which have #SpringBootTest annotation are failing with java.lang.IllegalStateException: Failed to load ApplicationContext
I have my application properties(application.properties) file in src/main/resources and the test application.properties file in src/text/resources
I have tried various annotations like
#ContextConfiguration()
#TestPropertySource(locations = "classpath:application.properties")
Still received the same error.
Below is the sample test class created.
package xxx.xx.xx.xxxx.controller
import org.junit.Assert;
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(classes = App.class)
#WebAppConfiguration
public class SampleTest {
//sample test case created to figure out
//test case runs successful when #SpringBootTest is not present
#Test
public void sampleTest1() {
int x= 2+3;
Assert.assertEquals(5, x);
}
}
I expect to able to run the test cases with that annotation.

Spring boot cucumber TestExecutionListener before database initalization

I want to create integration test with docker before cucumber test start. Inspired by: http://tech.asimio.net/2016/08/04/Integration-Testing-using-Spring-Boot-Postgres-and-Docker.html
But in my case the TestExecutionListener is not started before database initialization. I use Flyway for database migrations and it seems it tries to initialize first. For this a database connection required, which is not available, due the TestExecutionListener not being executed.
These are my classes:
#RunWith(Cucumber.class)
#CucumberOptions(
plugin = {"json:target/integration-cucumber.json"},
features = "src/test/resources"
)
public class CucumberIntegration {
}
And my test class which I will be extended by the cucumber steps:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = Application.class)
#SpringBootConfiguration
#ContextConfiguration
#TestPropertySource(locations="classpath:application.properties")
#TestExecutionListeners({
DockerizedTestExecutionListener.class,
DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class
})
public class SpringIntegrationTest {
}
When I change #SpringBootTest(classes = Application.class) to #SpringBootTest I see DockerizedTestExecutionListener being executed. Only it fails because it misses configuration from Application.class.
Anyone idea how to this with or without TestExecutionListener?
This will not work because the Cucumber.class JUnit runner doesn't support TestExecutionListeners.
You might think that your test steps are executed by the SpringRunner.class JUnit runner, but they aren't.
The #RunWith(SpringRunner.class) annotation on your SpringIntegrationTest class is basically useless here, since according to your post, your subclasses of SpringIntegrationTest contain Cucumber steps. However the SpringRunner expects JUnit #Test methods. Cucumber steps with #Given, #When, #Then etc. are ignored because SpringRunner doesn't know what to do with them.
What really executes your test steps is the #RunWith(Cucumber.class) annotation in your CucumberIntegration class. The Cucumber runner, however, doesn't give a damn about the TestExecutionListeners annotation that your steps definition class inherits from SpringIntegrationTest because it doesn't support such a feature.
Execution listeners are a Spring-only feature. You won't be able to do what you want to do, at least not as long as you use Cucumber.

JUnit Test Cases for Config

I have a javaconfig file that looks like this:
#Configuration
public class ServiceConfig {
#Autowired
FooBean someBean;
#Bean
#Scope(value="session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public FooService fooService() {
return new FooServiceImpl(someBean, fooB());
}
private Foo fooB() {
return new FooB();
}
}
And I have created a junit test file like so based on this stack answer :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = ServiceConfig.class)
public class ServiceConfigTest {
}
But I have a couple questions:
Should I test all my config files with this one junit test file? I have 4 config files in total including the ServiceConfig file, so in the ContextConfiguration should I just list them all out or have a junit test for each one indivually?
What am I supposed to test here? I tried reading this spring guide but I'm not really understand what behavior I should test here....just if something gets autowired successfully?
Should I test all my config files with this one junit test file? I
have 4 config files in total including the ServiceConfig file, so in
the ContextConfiguration should I just list them all out or have a
junit test for each one indivually?
In your test class, #ContextConfiguration must be positioned on the root of the class.
So for testing each configuration, you have to create a test class by Configuration.
What am I supposed to test here? I tried reading this spring guide but
I'm not really understand what behavior I should test here....just if
something gets autowired successfully?
Testing if autowired is successful seems not very useful. It would be as unit test that Spring feature works. If you want to unit test these classes, you should test your own processing. For the moment, you have not really. So, I am not sure that testing them has great value.
Test the intended behaviour of your system or individual units of functionally. As part of this the configs will be tested.
You don't need to make tests to make sure something is wired correctly. That should be implied on the basis that the functionality you are testing works.
You can aggregate multiple configurations into one configuration class using #Import.

Spring Injecting Beans from src folder in test folders

I have utility classes exposed as beans in my source folders. I want to use some of those utilities in my test classes written in junit 4. For example , I have a utility class that has methods which marshal an object into JSON string. I want to inject this utility bean in my test class. I am unable to inject these beans using Autowired annotation. Should I copy all these classes over to test folder?
Edit:
I am trying to inject jsonUtil. Below is how my code looks like.
import static org.junit.Assert.*;
import java.math.BigDecimal;
#RunWith(MockitoJUnitRunner.class)
#SpringApplicationConfiguration(classes = ProxyApplicationMock.class)
public class ProxyApplicationMock {
#Mock
public SoapClient soapClientMock;
private JsonUtil jsonUtil;
Main Class
public class ProxyApplication {
public static void main(String[] args) {
SpringApplication.run(ProxyApplication.class, args);
}
}
Your main classes can be seen by your test classes, but not the other way around. So no, you don't need to copy them.
If your utility class is declared as a Spring managed bean in your test Spring context configuration (the class -or XML file- declared in the #ContextConfiguration) which may and probably should be different from your main configuration.
Then you can inject it in any Spring managed class, which includes your test classes if it's using the SpringJUnit4ClassRunner.
EDIT:
To sum up what we discussed in the comments, the main problem is that your test runner is not a SpringRunner (alias for SpringJUnit4ClassRunner), and thus JUnit is not running your test in a Spring context. Have a look at a test example here.
The simplest test case will look like this.
#RunWith(SpringRunner.class)
#SpringBootTest
public class CityRepositoryIntegrationTests {
#Autowired
private MySpringBean springBean;
//...
}
But as often with Spring Boot, there's some magic happening behind. #SpringBootTest is a convenient annotation that will detect automatically a class annotated with #SpringBootConfiguration, meaning if you don't have a specific Spring configuration for your test, it will use your main Spring configuration, and thus include and instanciate all the beans for your main app, and that's not usually what we want in a unit test cause we want to test a class independently by mocking its dependencies.
What you can do, is provide the Spring compenent classes you want to include in your tests, as such:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = MySpringBean.class)
public class CityRepositoryIntegrationTests {
#Autowired
private MySpringBean springBean;
#Mock
private MyMockedSpringBeanDependency mocked;
//...
}
This question is to Matt, since adding comment is throwing error saying only one additional use can be notified.
NOTE: Not an Answer
I have an Application class & many config classes which are imported in Application class. Earlier it was #Configuration, which I converted to #SpringBootConfiguration in Application class and the actual Config class, whos bean I am trying to mock. Ended up in
java.lang.NoSuchMethodError: org.springframework.boot.SpringApplication.<init>([Ljava/lang/Object;)V
at org.springframework.boot.test.context.SpringBootContextLoader.getSpringApplication(SpringBootContextLoader.java:121)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:84)
Please suggest How do I mock, I have the same setup as specified in the ticket.
#Bean
public CacheManager cacheManager()
{
EhCacheManagerFactoryBean factoryBean = new EhCacheManagerFactoryBean();
factoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
factoryBean.setShared(true);
return new EhCacheCacheManager(factoryBean.getObject());
}
}

Categories

Resources