Viewed   5k times

I'm trying to run the mvn integration-test phase and I'm getting Failed to load ApplicationContext error when the integration tests are executed (the unit tests get executed correctly). I'm running my tests with the SpringJUnit4ClassRunner class using.

This is the full stack trace:

2017-02-09 03:22:15.705 [main] ERROR o.s.t.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@5c072e3f] to prepare test instance [com.dentilax.app.accountservice.AccountServiceIT@768b970c]
java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.IllegalStateException: Neither GenericXmlContextLoader nor AnnotationConfigContextLoader was able to load an ApplicationContext from [MergedContextConfiguration@71623278 testClass = AccountServiceIT, locations = '{}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]].
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:263)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
    ... 25 common frames omitted

Also, I'm using an archetype, you can see the annotated Configuration classes here. What am I doing wrong?

This is my Test class:

@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
public class PatientServiceIT {

    private static final String EMAIL = "account@test.com";
    private static final String NAME = "test";
    private static final String SURNAMES = "account";
    private static final String PASSWORD = "testaccount";
    private static final String POSTAL_CODE = "15002";
    private static final String MOBILE_NUMBER = "694749217";

    @Autowired
    private AccountRepository accountRepository;

    @Autowired
    private PatientRepository patientRepository;

    @Autowired
    private PatientService patientService;

    private PatientDetails createPatientDetails() {
        return new PatientDetails(EMAIL, PASSWORD, NAME, SURNAMES, MOBILE_NUMBER, POSTAL_CODE);
    }

    private Account createPatient() {
        Account patientAccount = new Account(EMAIL, PASSWORD, NAME, SURNAMES, Role.ROLE_DENTIST);
        Patient patient = new Patient(POSTAL_CODE, MOBILE_NUMBER);
        patientAccount.setPatient(patient);
        return patientAccount;
    }

    @Test
    public void savePatient() {
        // call
        Patient patient = patientService.save(createPatientDetails());

        // assert
        assertEquals(patient.getAccount(), createPatient());
    }

}

PS: I'm suing maven failsafe for the integration-test goal and surefire por the test goal.

 Answers

3

You are missing the definition of the context with the @ContextConfiguration(classes = ...) annotation in your test. As classes you might define single configuration(s) or your whole production application context (that includes all the others). The benefit of declaring just the configuration classes you need is that the whole bootstrapping for the test is faster.

Note: Spring tests cache their specified application context. If you have to run 9/10 tests with the whole config it will take less time to use the whole config again than declaring a new set of context config. But you should aim to get a small config footprint for your integration tests so you can focus on the domain slice you are working in and not have to handle or maintain other context configurations.

In general tests run with SpringJUnit4ClassRunner expect to have an application context to run with. Further reading: Link to the spring docs

Sunday, December 4, 2022
 
2

Failing loading xxxx.dll is an indication that PHP can't load the extension file. This could have several reasons:

  1. The file does not exist ? check if it does

  2. The permissions on the file are incorrect ? check the permissions

  3. The file is of "the wrong extension type". Which can be either:

    • the extension is for the wrong wrong PHP version
    • the extension is of the wrong bitness (32 vs 64bit)
    • the wrong TS variant (NTS vs ZTS)
    • the wrong "debug mode" build of PHP (either debug, or nodebug)

The API type (except for bitness, which you can check with echo PHP_INT_SIZE;; 4 is 32bit, and 8 is 64bit) is reflected in the "Zend Extension Build" output in php -i or phpinfo().

You can use Xdebug's wizard to tell you which exact file to download for your specific set-up.

Saturday, November 26, 2022
 
1

Here's an updated (for 2019) version of the accepted answer from @rozky (a lot has been changed in both the Mongo and Embedded MongoDB libraries).

package com.example.mongo;

import com.mongodb.BasicDBObject;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import de.flapdoodle.embed.mongo.MongodExecutable;
import de.flapdoodle.embed.mongo.MongodProcess;
import de.flapdoodle.embed.mongo.MongodStarter;
import de.flapdoodle.embed.mongo.config.IMongodConfig;
import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
import de.flapdoodle.embed.mongo.config.Net;
import de.flapdoodle.embed.mongo.distribution.Version;
import de.flapdoodle.embed.process.runtime.Network;
import java.util.Date;
import org.junit.After;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;

public class EmbeddedMongoTest
{
    private static final String DATABASE_NAME = "embedded";

    private MongodExecutable mongodExe;
    private MongodProcess mongod;
    private MongoClient mongo;

    @Before
    public void beforeEach() throws Exception {
        MongodStarter starter = MongodStarter.getDefaultInstance();
        String bindIp = "localhost";
        int port = 12345;
        IMongodConfig mongodConfig = new MongodConfigBuilder()
        .version(Version.Main.PRODUCTION)
        .net(new Net(bindIp, port, Network.localhostIsIPv6()))
        .build();
        this.mongodExe = starter.prepare(mongodConfig);
        this.mongod = mongodExe.start();
        this.mongo = new MongoClient(bindIp, port);
    }

    @After
    public void afterEach() throws Exception {
        if (this.mongod != null) {
            this.mongod.stop();
            this.mongodExe.stop();
        }
    }

    @Test
    public void shouldCreateNewObjectInEmbeddedMongoDb() {
        // given
        MongoDatabase db = mongo.getDatabase(DATABASE_NAME);
        db.createCollection("testCollection");
        MongoCollection<BasicDBObject> col = db.getCollection("testCollection", BasicDBObject.class);

        // when
        col.insertOne(new BasicDBObject("testDoc", new Date()));

        // then
        assertEquals(1L, col.countDocuments());
    }

}
Tuesday, September 20, 2022
2

What to put in the app context file. The way the TestContext Framework works is that it allows you to reuse app wiring in the context of your integration tests. So for the most part, there isn't anything special to tests you'd put inside your app context config files. If your controller has a service bean dependency in your app, then it will have that in your integration test too. If your DAO has a SessionFactory in your app, then same for your integration test. That way you don't have to wire all that stuff up all over again when you write integration tests. Very cool.

I said for the most part above because there's at least one exception that comes to mind. Normally your app will use JNDI to locate a DataSource, but in an integration test (at least an out-of-container integration test), you won't normally have a JNDI environment available. So you should typically isolate the DataSource bean creation to a separate file, and use a JNDI version for your live app and a non-JNDI version (e.g. just create a straight BasicDataSource, say) for your integration test. Here's an example of the former:

<jee:jndi-lookup id="dataSource" jndi-name="jdbc/myStoreDS" resource-ref="true"/>

and here's an example of the latter:

<bean id="dataSource"
    class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close"
    p:driverClassName="${dataSource.driverClassName}"
    p:url="${dataSource.url}"
    p:username="${dataSource.username}"
    p:password="${dataSource.password}" />

These would go in separate files. The first might go in beans-datasource.xml for normal app use and the second in beans-datasource-it.xml for integration tests. The configuration that's common to normal app use and integration tests (i.e., the vast majority of your bean config in most cases) should be in a common config file or files.

Also, Spring 3 introduces a new jdbc namespace that allows you to create an embedded database, like an HSQLDB database or a Derby database, etc. It looks like this:

<jdbc:embedded-database id="dataSource">
    <jdbc:script location="classpath:hsql/schema.sql" />
    <jdbc:script location="classpath:hsql/test-data.sql" />
</jdbc:embedded-database>

That would replace the BasicDataSource config described above, if you want to use this.

Why the error is happening. The error you are seeing is happening because your @ContextConfiguration value is implicitly indicating that the app context file should be on the classpath. IMPORTANT: Remove the /resources piece. That is Maven innards; when it builds your JAR or WAR, it copies the contents of the resources directory into your classpath, not resources itself. That should help.

EDIT:

To address the "no symbol found" errors, you will need to add your test dependencies to your Maven POM. This will be JUnit and the Spring Test module as well, both with <scope>test</scope>. In addition if you are using a mock framework like Mockito, you will need to add that dependency (with test scope) to your POM as well. Try that and please report back on what happens.

Friday, December 16, 2022
 
4

When running as junit test using Spring Test annotations, you need to use classpath in the locations like this

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/context.xml")

And I don't use any resources definition in the pom.xml. You can remove that and try like this.

Wednesday, September 28, 2022
 
dhh
 
dhh
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share