I'm having a problem whereby spring is re-creating my beans and re-auto wiring after each junit test has been run. I only want spring to do this once, on the post construct of the test class, which is what I've configured it to do.
I've also tried setting the #DirtiesContext class mode to AFTER_CLASS, but this still didn't solve the issue.
Any ideas?
Cheers.
You can create a class:
#SpringJUnitConfig(classes = {ConfigClassOne.class, ConfigClassTwo.class, ConfigClassThree.class})
public abstract class ModelTest {}
and extend it in the test classes. Beans will not be recreated because the application contexts are already mentioned in the annotation.
Related
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
Should I always start Spring context during integration tests? (I mean using #SpringBootTest annotation)
Currently I'm writing integration test that involves a few classes and in order to make it faster I create object graph by hand (i.e. I don't start Spring IoC container). So currently my integration test (written in Spock) looks like this:
class UserConverterIT extends Specification {
UserConverter converter = new UserConverter(new UserDtoFactory(new UserGroupPolicy()))
def 'should ...'() {
when:
converter.convert(...)
then:
...
}
}
Alternatively I could add #SpringBootTest annotation, put #Autowire above UserConverter field and all dependecies would be injected automatically. However, the first approach is much faster. Is there something wrong in this approach?
As you said the #Autowired annotation would inject all dependencies and load the whole context automatically. Your approach is also working but its really fragile!
How can you guarantee that in your tests you never need some beans which you didn't manually new them?
Also there is another important thing. When you let the spring to inject the dependencies, if there is a problem on declaring the beans, problem would show on test phase, but in your approach they won't identify.
Also you might sometimes #Autowired an interface which told spring to get the implementation on runtime. For example you have a parent module which has an interface that implements in the child module. When you want to write a test case in parent you don't have access to child implementation to make new of that.
I have a very basic scenario where I just need to call a method which has an annotation. This annotation simply calls an AspectJ advice. I just need to make sure that the advice is being called, ideally via a mock verify. Tests are being run using TestNG and mocking using Mockito. Spring is version 4.
class under test
public class MyClassUT
{
#MyAnnotation
public myMethod...
{
...
}
}
test class
#ContextConfiguration(classes = {SpringTestConfig.class})
#WebAppConfiguration
public class MyClassUtTest extends AbstractTestNGSpringContextTests
{
#InjectMocks private MyClassUT mine;
#BeforeMethod
public void init()
{
MockitoAnnotations.initMocks(this);
}
#Test
public void testMyMethod()
{
mine...
}
}
The problem is that the advice is being called and everything is OK, except for the fact that the advice class is instantiated once by spring and another time before calling the said method. The instance being used is the latter which of course has no dependencies injected so it fails. What I am trying to do is provide spring with a mock of my advice or at least inject a mock of the service it depends on and ask AspectJ to use that existing instance.
I have tried using factory methods for the advice, spring test configurations etc, however nothing seems to be working. I have tried also with EnableAspectJautoproxy to no avail, instantiated the aspect with a #Bean annotation, also as a factory method - but nothing works well unfortunately.
(It is also interesting to note that when I enable AspectJ in eclipse, the aspect test also run in maven and as far as I know, nothing changes in pom.xml.)
So, my question is:
How do I make the test use an instance of the aspect I or spring create so that when the method MyMethod is called, its dependencies are in place , or the mock version is used?
This problem is basically equivalent,
but
How do I do this without a single line of XML config - I've seen using an apectOf factory method config being mentioned a lot, but I need a pure annotation solution, if possible;
Works with TestNg not JUnit;
Thank you!
I have a maven spring project (latest version) and I want to write some junit tests (latest version).
The issue I have is that my spring beans are autowired, and when I call them from junit test, I get null pointer exceptions, as spring doesn't autowire them.
How can I load the context so that things are autowired?
Have you studied Testing chapter in Spring reference documentation? Here is an example you should start with:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class MyTest {
#Resource
private FooService fooService;
// class body...
}
If you are in com.example.MyTest in /src/test/java, you will need /src/test/resources/com/example/MyTest-context.xml - but the exceptions will show you the way.
This is a possibility:
#RunWith(SpringJUnit4ClassRunner.class)
// ApplicationContext will be loaded from "/applicationContext.xml"
// in the root of the classpath
#ContextConfiguration({"/applicationContext.xml"})
public class MyTest {
// class body...
}
Usually it's a good idea though to have a test-applicationContext for your test infrastructure.
You should use the SpringJUnit4ClassRunner on your test classes, and use #Resource (or #Autowired) on the field in your test class that contains the bean. You should consider having a special test context Spring configuration that uses stubs so that your tests are genuine unit tests, and don't rely on the whole application context.