Page 1 of 2 12 LastLast
Results 1 to 10 of 13

Thread: @RunWith(...) @ComponentScan does not work

  1. #1

    Default @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.
    Spring 3.X, Web Flow 2.X, Java 6, STS 2.7.0, Maven, OS X

  2. #2
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,625

    Default

    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 at 09:25 AM. Reason: Fixed source.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  3. #3
    Join Date
    Jul 2010
    Posts
    139

    Default

    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 at 09:58 AM.

  4. #4

    Default

    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.
    Spring 3.X, Web Flow 2.X, Java 6, STS 2.7.0, Maven, OS X

  5. #5

    Default

    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 at 07:03 AM. Reason: Ergänzung
    Spring 3.X, Web Flow 2.X, Java 6, STS 2.7.0, Maven, OS X

  6. #6
    Join Date
    Jul 2010
    Posts
    139

    Default

    @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.

  7. #7

    Thumbs up 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 {}
    ... 
    Spring 3.X, Web Flow 2.X, Java 6, STS 2.7.0, Maven, OS X

  8. #8
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,625

    Default

    Quote 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.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  9. #9

    Default

    I'm sure it was an anti-copy-paste-start-thinking pattern. ;-)
    Spring 3.X, Web Flow 2.X, Java 6, STS 2.7.0, Maven, OS X

  10. #10
    Join Date
    Jul 2010
    Posts
    139

    Default

    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.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •