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.
Related
Precondition
I have two XML configuration files one in src/main/resources which is called main-config.xml and used by the codebase, and one in src/test/resources which is called test-config.xml.
I wrote some integration tests and I wanted to load the test-config.xml into the context in the following way
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.DEFINED_PORT,classes = { IntegrationTest.ITContext.class})
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class IntegrationTest {
#Configuration
#EnableAutoConfiguration
#PropertySource("classpath:application.properties")
#ImportResource("classpath:test-config.xml")
public static class ITContext{
....
}
}
The problem
In my main-config.xml there are some beans which I don't want to use in my test-config.xml. I have deleted these beans from test-config.xml, but for some reason they are still loaded into the integration tests context.
What I want to achieve?
I want to fully separate the main config file from the test config file.
Question
How can I achieve the wanted result with XML configuration? Which annotations am I missing?
Thanks in advance!
I have a strange issues. I have a series of test that sometimes use messages on Kafka queue that is received form the listener (all within same distance of the application) and then processed. Kafka is instantiated with the help of Docker.
In the test class is have a repository annotated with #MockBean, and that repository is used also within the Kafka listener.
When is rune the test inside Idea all work and within the listener the repository interface is exalt the mocked bean.
When the tests are executed using Gradle on terminal, sometimes not always, within the lister is used the real repository and not the mocked one.
Thank you for the help.
I have found the problem, seems that the problem was the transaction. In Kafka I use it. Any the digging around an after some search I have found the solution.In tests I create a class for the test configuration that create the mock of the bean as this:
#TestConfiguration
public class ConfMock {
#Bean
#Primary
public IdentityManagementRepository identityManagementRepository() {
return mock(IdentityManagementRepository.class);
}
}
and in the real test classes i use the annotation #Import(ConfMock.class)like this:
#Import(ConfMock.class)
#AutoConfigureMockMvc
#SpringBootTest()
#ActiveProfiles("test")
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class ApplicationControllerTest extends AbstractTest {
}
This solution born from this answer, I have bring out the configuration in a separate class, and it work.
Thanks you
I'm trying to execute a unit test for a service class that has an #Async("asyncExecutor") annotated method. This is a plain JUnit test class with no Spring runners and no intention of using Spring at all in the unit test. I get the exception,
BeanFactory must be set on AnnotationAsyncExecutionAspect to access qualified executor 'asyncExecutor'
Where asyncExectuor is the name of the bean to be used during normal execution. My configuration class looks like this and I solved that previous error message at runtime by adding the mode = AdviceMode.ASPECTJ portion. This service works at runtime without issue in an Async way.
#Configuration
#EnableAsync(mode = AdviceMode.ASPECTJ)
public class AsyncConfiguration {
#Bean(name = "asyncExecutor")
public Executor asyncExecutor() {
...
}
}
I don't understand why the Spring context is being constructed at all in the unit test. The test class is simply annotated #Test on the methods with no class annotations and no mention of Spring. I was hoping to unit test this service class method as a regular method ignoring the async nature, but the annotation is being processed for some reason.
I'm contributing to a much larger gradle + Spring 4 project that I'm not fully knowledgeable about. Is there anything I should be looking for to see if a Spring context is being created by default for all tests?
As you noticed, Spring context is not loaded, that is the reason of your error. Try to initialize Spring context in your test by adding #RunWith and #ContextConfiguration annotations
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());
}
}
I am trying to write a unit test for a static method which takes a class and method name and does some reflection to call the method with arguments and store the results. I'm using spring-boot.
My test actually works when I run the full suite, but when I run the test as standalone it fails. The problem is that I've created a mock class (a hand written mock, not using mockito or easymock) which I want the static method to use. However, the reflection can not detect my mock class because the class has not been loaded into the applicationContext by spring-boot. Here is the line that fails:
T proxy = SpringApplicationContext.getBean(clazz);
SpringApplicationContext definition:
#Component
public class SpringApplicationContext implements ApplicationContextAware
{
private static ApplicationContext applicationContext_;
#Override
public void setApplicationContext(ApplicationContext applicaitonContext) throws BeansException {
applicationContext_=applicaitonContext;
}
public static <T> T getBean(Class<T> requiredType) throws beanException {
return applicationContext_.getBean(requiredType);
}
*note, I had to retype by hand, please assume obvious syntax errors are typos.
so basically my applicationContext is not being set or defined. I only need one mock bean in the applicationContext, I could do it by hand, but is there a more spring approach using annotations?
It turns out that my test didn't work rather the were run stand alone or part of a suite, I had a separate issue with using the wrong annotations for #BeforeTest which masked the defect when running the whole suite.
The fix was pretty simple. I added the SpringApplicationConfiguration annotation above my test:
#SpringApplicationConfiguration(classes =
{
MockController.class,
SpringApplicationContext.class
}
public class MyTest extends AstractTestNGSpringContextTests
There are two parts to this. The #SpringApplicationCOnfiguration loads only those values I listed. I could have pointed to configuration classes, but that would ultimately load most of the beans in my enviroment which is overkill for a unit test. So I load the two #component objects needed in my ApplicationContext for my unit test to work only.
I also had to extend AbstractTestNGSpringContextTests because It's the only way to get spring to play nice with the TestNG kit were using for our tests. If others are using junit tests instead of TestNG don't extend the AbstracTestNGSpringContextTests, instead I believe your want to add the annotation:
#RunWith(SpringJUnit4ClassRunner.class)
Though I haven't used it since I'm not using junit.
Hopefully this answer saves others who are trying to figure out how to load only a few classes instead of the entire enviroment (most examples I found want you to load configuration files that will load every bean, which is slow and honestly undesirable in a unit test).
Arguably I should still have mocked out the SpringApplicationContext entirely, I'm lazy and sloppy :)