Reputation: 502
Some small infos beforehand:
Spring Boot 1.3.0
Spring Mongo 1.3.3
Spring Security 3.1.4
Spring Security Cas 4.0.2
Flapdoodle Embedmongo 1.46.0
Right now, we have an abstract test class annotated with
@RunWith(SpringJUnit4ClassRunner.class)
, @SpringApplicationConfiguration(TestConfig.class)
and @WebAppConfiguration
.
The TestConfig-class looks like this:
@Configuration
@EnableAutoConfiguration(exclude = { EmbeddedMongoAutoConfiguration.class })
@ComponentScan(value = { "package1", "package2" })
public class TestConfig {
}
As you see, it scans everything in those 2 packages, and fetches several other configuration classes as well:
@Configuration
// needed if working with Spring-Data-Repository interfaces and subprojects
// http://stackoverflow.com/questions/29084824/spring-repository-components-not-found-in-gradle-subproject-springboot
@EnableMongoRepositories({ "package2.subpackage" })
public class ModelConfiguration {
}
and
@Configuration
@EnableAutoConfiguration(exclude = { EmbeddedMongoAutoConfiguration.class })
@EnableMongoRepositories(basePackages = { "package2" })
public class TestMongoConfiguration {
private static final String DESTROY_METHOD_CLOSE = "close";
private static final String DESTROY_METHOD_STOP = "stop";
private static final MongodStarter STARTER = MongodStarter.getDefaultInstance();
@Autowired
private MongoProperties mongoProperties;
@Autowired(required = false)
private MongoClientOptions mongoClientOptions;
@Autowired
private Environment environment;
@Bean(destroyMethod = DESTROY_METHOD_CLOSE)
public MongoClient mongo() throws IOException {
Net net = mongodProcess().getConfig().net();
mongoProperties.setHost(net.getServerAddress().getHostName());
mongoProperties.setPort(net.getPort());
return mongoProperties.createMongoClient(this.mongoClientOptions, environment);
}
@Bean(destroyMethod = DESTROY_METHOD_STOP)
public MongodProcess mongodProcess() throws IOException {
return mongodExecutable().start();
}
@Bean(destroyMethod = DESTROY_METHOD_STOP)
public MongodExecutable mongodExecutable() throws IOException {
return STARTER.prepare(mongodConfig());
}
@Bean
public IMongodConfig mongodConfig() throws IOException {
return new MongodConfigBuilder().version(Version.Main.PRODUCTION).build();
}
}
And this is part of my test class:
@SpringApplicationConfiguration(classes = TestClass.TestConfiguration.class)
public class TestClass extends AbstractTest {
@Order(Ordered.HIGHEST_PRECEDENCE)
public static class TestConfiguration {
@Bean
@Primary
public FooRepository fooRepository() {
FooRepository mock = mock(FooRepository.class);
// mockbehaviour
return mock;
}
@Bean
@Primary
public FooDao fooDao() {
FooDao mock = mock(FooDao.class);
//Mock behaviour
return mock;
}
@Bean
@Primary
public BarDao barDao() {
BarDao mock = mock(BarDao.class);
//MockBehaviour
return mock;
}
@Bean
@Primary
public BarRepository barRepository() {
BarRepository mock = mock(BarRepository.class);
return mock;
}
}
I am creating several requests now which are passed to the superclass for security testing, and (since all tests have only one successful case anyway) I then try to verify the corresponding calls to the Daos and Repositories via verify(mock).
The Beans are injected to the Controller by @Resource
, the same way I am using them in the test class.
For some reason, the Daos are working as intended (are created, behaviour is specified, are called and can be verified), the Repositories are not - the regular proxies are created and used. Before using @Order(Ordered.HIGHEST_PRECEDENCE)
, the bean creation was simply skipped (and logged as such) since the top-level bean already registered denied being overwritten.
After resorting to this, the Repository-beans have been overridden instead of skipped (and, of course, been logged as such). The @Primary
at bean level was supposed to make sure the mocks are used instead of the actual beans created by the component scan - and on other test instances, which do not start up the entire application and the embedded Mongo, this works as intended - but here, it does not.
@Order
@EnableMongoRepositories
-configurationsI have been looking for several days now, always and the only possible solutions I have stumbled upon are: create an xml-configuration (which is a no-go, since we are supposed to create everything without the need for xml-files), use Fongo (which would require to import a new dependency for this one step, as the Database-tests are happening somewhere else entirely, and then removing it), or disable the bean overriding (which I have absolutely no idea on doing and the Spring docs are not really helpful - yes, the method is there, but whenever I try to do this, it does not affect the current context).
Upvotes: 3
Views: 5860
Reputation: 1760
Sorry this would fit more in a comment rather than an answer, but the formatting is too bad...
No idea why it doesn't work, however did you try to using explicit import of @Configuration beans versus usage of ComponenScan?
e.g.:
@SpringApplicationConfiguration(classes = TestClass.TestConfiguration.class)
public class TestClass extends AbstractTest {
@Configuration
@Import( TestConfig.class )
public static class TestConfiguration {
//...
}
}
@Configuration
@EnableAutoConfiguration(exclude = { EmbeddedMongoAutoConfiguration.class })
// @ComponentScan(value = { "package1", "package2" }) // GET RID OF THIS
@Import( { TestMongoConfiguration.class /*, OtherConfig.class, ... */ } )
public class TestConfig {
}
This way you can control the order on how the configurations get loaded.
Upvotes: 3