Announcement Announcement Module
Collapse
No announcement yet.
@RunWith(...) @ComponentScan does not work Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • @RunWith(...) @ComponentScan does not work

    Hi!

    Yes I searched the forum, I used Google, but I'm out of ideas and keywords to search with now.

    Problem: I have a new Project with Spring 3.1M2 and I want to run JUnit tests like the following:
    Code:
    @RunWith(SpringJUnit4ClassRunner.class)
    @ComponentScan(basePackages = {"de.my.packages"})
    public abstract class AbstractAmqpTests {
    ...
    }
    But, as you may guess, it does not work.
    I have no XML Configs in my Project, just Config-Classes like those:
    Code:
    @Configuration
    public class DataSourceConfig {
    	@Bean
    	public DataSource dataSource() throws ClassNotFoundException {
    		...
    	}
    The application works with a Main-Application, which works:
    Code:
    public class Main {
    
    	public static void main(String[] args) {
    AnnotationConfigApplicationContext ctx = 
    new AnnotationConfigApplicationContext("de.my.packages");
    System.out.println("Ready.");
    	}
    I cannot find an example how to run the tests with a Component Scan, execpt of the following solution, but there have to be a better one instead of list every Config-Class:
    Code:
    @ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = {DataSourceConfig.class,
      JobDetailConfig.class, RabbitServerConfig.class, SchedulerFactoryConfig.class, TriggerConfig.class,
      MessageHandlerConfig.class, QuartzSchemaHelper.class, CalendarHandler.class, HostHandler.class,
      ServiceHandler.class, ConfigMessageHandler.class})
    The Exception on starting the test:
    Code:
    java.lang.IllegalStateException: Failed to load ApplicationContext
    	at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:181)
    	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
    ...
    Caused by: java.lang.IllegalArgumentException: Can not load an ApplicationContext with a NULL 'contextLoader'. Consider annotating your test class with @ContextConfiguration.
    	at org.springframework.util.Assert.notNull(Assert.java:112)
    	at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:121)
    Btw: When I follow the hint to add a @ContextConfiguration then he tries to load a XML-File, which I not have. I even tried to give him such a XML with just a <context:component-scan /> in it, but that does not work either.

  • #2
    ComponentScan isn't going to work that way... You will have to provide the names of the Configuration classes to load by the unit test.

    You could probaly trick it by removing the config classes fromthe ContextConfiguration, create an internal (to the test class) class and annotate that with @Configuration and @ComponentScan... It might work but no garuantees....

    Code:
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(loader = AnnotationConfigContextLoader.class)
    public abstract class AbstractAmqpTests {
    
     @Configurable
     @ComponentScan(basePackages = {"de.my.packages"})
     static class TestConfiguration {}
    
    }
    You might want to limit this @ComponentScan to @Configuration classes only, because els eyou might run into issues with other @ComponentScans in your other @Configuration classes (not sure if you have it but just wanted to share it).
    Last edited by Marten Deinum; Jul 7th, 2011, 10:25 AM. Reason: Fixed source.

    Comment


    • #3
      I would also have your BaseTestClass extend either AbstractJUnit4SpringContextTests or AbstractTransactionalJUnit4SpringContextTests:

      Code:
      @ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes={AppConfig.class, DataSourceConfig.class,
        JobDetailConfig.class, RabbitServerConfig.class, SchedulerFactoryConfig.class, TriggerConfig.class,
        MessageHandlerConfig.class, QuartzSchemaHelper.class, CalendarHandler.class, HostHandler.class,
        ServiceHandler.class, ConfigMessageHandler.class})
      @TransactionConfiguration(transactionManager = "txManager")
      public abstract class BaseTestClass extends AbstractTransactionalJUnit4SpringContextTests {
      
      }
      Also configure component scanning somewhere...

      Code:
      @Configuration
      @EnableTransactionManagement
      @ComponentScan(basePackages = "de.my.packages", excludeFilters = @Filter(type = FilterType.ANNOTATION, value = Configuration.class))
      public class AppConfig {
      }
      Then setup each of your tests to use your base test setup...

      Code:
      public class ExampleTests extends BaseTestClass
      {
        @Test
        public void someTest()
        { ... }
      }
      Last edited by jzcfk9; Jul 7th, 2011, 10:58 AM.

      Comment


      • #4
        Ok, first, thank you for your high quality answers!

        @"Marten Deinum": I read somewhere in the Doc about your suggest, but I think, the inner class has to have another name ... but I can't find it there. Damn, where is it? With your solution the Test is unable to autowire my beans to the abstract test. ("No canidate found ...")

        @jzcfk9: Ok, thats another solution. Do I really have to define a txManager even if I have such a bean in my context, which produces one? Ok, I'll read that in docs later. One Problem with your suggest is the @Filter thing. I don't have such a Annotation in my libs. My spring-test artifact version equals to spring-core and all the other versions.

        Comment


        • #5
          Solution for my @Filter-Problem:
          Code:
          @ComponentScan(basePackages = "de.hlsolutions.hlmonitor.scheduler", excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class))
          And I found the site where the inner-class definition is explained: It wasn't in the docs, it was a blog post: SpringSource Blog
          Last edited by sja; Jul 11th, 2011, 08:03 AM. Reason: Ergänzung

          Comment


          • #6
            @TransactionalConfiguration(transactionManager="tx Manager") is not defining another bean. This is used to tell Spring's testing framework the name of your PlatformTransactionManager. Refer to API docs for further details. Good luck.

            Comment


            • #7
              Solved

              Ok, finally i got it with the inner Class. I had to rename my packages from my.project.subname.tests to my.project.tests.subname because of ComponentScan. The Filter did not work for me, because it filters all my configurations.

              @"Marten Deinum": There was a little error in you suggestion: The inner class has to be annotated with @Configuration, not with @Configurable.

              @jzcfk9: I picked up your extend-hierarchy.

              PHP Code:
              package de.company.project.tests.subproject;

              @
              RunWith(SpringJUnit4ClassRunner.class)
              @
              ContextConfiguration(loader AnnotationConfigContextLoader.class)
              @
              TransactionConfiguration(transactionManager "txManager"defaultRollback false)
              public abstract class 
              AbstractAmqpTests extends AbstractTransactionalJUnit4SpringContextTests {
                  @
              Autowired
                  
              protected RabbitAdmin        rabbitAdmin;
                  @
              Autowired
                  
              protected RabbitTemplate    rabbitTemplate;
                  @
              Autowired
                  
              protected DataSource        dataSource;
                  @
              Autowired
                  Scheduler                    scheduler
              ;
                  @
              Autowired
                  JdbcTemplate                jdbcTemplate
              ;

                  @
              Configuration
                  
              @ComponentScan(basePackages = {"de.company.project.subproject"})
                  static class 
              ContextConfiguration {}
              ... 

              Comment


              • #8
                Originally posted by sja
                @"Marten Deinum": There was a little error in you suggestion: The inner class has to be annotated with @Configuration, not with @Configurable.
                Thats what you get when you type code in the reply window from the top of your head . But it probably wasn't that hard to fix my mistake . Anyway glad it worked out.

                Comment


                • #9
                  I'm sure it was an anti-copy-paste-start-thinking pattern. ;-)

                  Comment


                  • #10
                    Good news! One minor note is that you don't need the @RunWith(SpringJUnitClassRunner.class) annotation on your AbstractAmqpTests class. This is already picked up for you since you extend AbstractTransactionalJUnit4SpringContextTests.

                    Comment


                    • #11
                      Won't it be better to remove the extend and leave the Annotation for a looser coupling?

                      Comment


                      • #12
                        Yes, those base test classes provided by Spring are just meant for convenience. If you remove the extends AbstractTransactionalJUnit4SpringContextTests, then you would need to add all of the annotations that base class provides:

                        @RunWith(SpringJUnit4ClassRunner.class)
                        @TestExecutionListeners( { DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class, TransactionalTestExecutionListener.class })
                        @Transactional

                        Comment


                        • #13
                          Good news!

                          After the things of the beginning of this thread now I use Profiles. And those even work with my tests like so:
                          PHP Code:
                          @RunWith(SpringJUnit4ClassRunner.class)
                          @
                          ContextConfiguration(loader AnnotationConfigContextLoader.class)
                          @
                          ActiveProfiles("devOra")
                          @
                          TransactionConfiguration(transactionManager "txManager"defaultRollback false)
                          public abstract class 
                          AbstractAmqpTests extends AbstractTransactionalJUnit4SpringContextTests {
                              @
                          Autowired
                              
                          protected RabbitAdmin        rabbitAdmin;
                              @
                          Autowired
                              
                          protected RabbitTemplate    rabbitTemplate;
                              @
                          Autowired
                              
                          protected DataSource        dataSource;
                              @
                          Autowired
                              Scheduler                    scheduler
                          ;
                              @
                          Autowired
                              JdbcTemplate                jdbcTemplate
                          ;

                              @
                          Configuration
                              
                          @ComponentScan(basePackages = {"de.company.project.subproject"})
                              static class 
                          ContextConfiguration {} 
                          The trick is the @ActiveProfiles("devOra") on the test-class. "devOra" is the profile-name on a configuration-bean.
                          Tip: Use more than one profile name! In my case, I will switch to Profile "ora","hsql" and "dev".
                          Spring-Blog: http://blog.springsource.com/2011/02...ucing-profile/
                          Last edited by sja; Jul 13th, 2011, 09:48 AM. Reason: typo

                          Comment

                          Working...
                          X