Martin Kňažko
Martin Kňažko

Reputation: 3

PlayFramework 2.5 - Testing not using in-memory databse

I have been following tutorials on PlayFramework, but it seems that they are all outdated and for older version of Play.

I want to try JUnit test using mysql databse not h2 in-memory database.

I am using ebean ORC (which clearly has different api than it used to have inside play 2.2, and the api is not really well documented).

Anyway I want to try JUnit test on mysql databse, but I am always getting a configuration error.

This is how the JUnit test class looks:

public class ModelsTest extends WithApplication {
    
    public  Application app;
    
    
    @Before
    public void setUp() throws FileNotFoundException, IOException {
        java.util.Properties externalProps=new java.util.Properties();
        externalProps.load(new FileInputStream("resources/test-ebean.properties"));
        ServerConfig config = new ServerConfig();
        config.setName("test");
        config.setDefaultServer(true);
        config.loadFromProperties(externalProps);
        EbeanServer server = EbeanServerFactory.create(config);
        
       
        app = Helpers.fakeApplication();
        
        Helpers.start(app);
       

    }
    
    @Test
    public void createAndRetrieveUser() {
        new User("[email protected]", "admin", "admin").save();
        User bob = User.find.where().eq("email", "[email protected]").findUnique();
        assertNotNull(bob);
        assertEquals("admin", bob.login);
    }
    
     @After
    public  void stopApp() {
        Helpers.stop(app);
        
    }

test-ebean.properties file :

ebean.ddl.generate=true
ebean.ddl.run=true

datasource.default=db

datasource.db.username="root"
datasource.db.password="root"
datasource.db.databaseUrl="jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8"
datasource.db.databaseDriver=com.mysql.jdbc.Driver

When running test I am getting this error:

[error] Test ModelsTest.createAndRetrieveUser failed:` play.api.Configuration$$anon$1: Configuration error[null], took 4.969 sec
    [error]     at play.api.Configuration$.configError(Configuration.scala:154)
    [error]     at play.api.Configuration.reportError(Configuration.scala:806)
    [error]     at play.Configuration.reportError(Configuration.java:366)
    [error]     at play.db.ebean.DefaultEbeanConfig$EbeanConfigParser.parse(DefaultEbeanConfig.java:81)
    [error]     at play.db.ebean.DefaultEbeanConfig$EbeanConfigParser.get(DefaultEbeanConfig.java:60)
    [error]     at play.db.ebean.DefaultEbeanConfig$EbeanConfigParser.get(DefaultEbeanConfig.java:44)
    [error]     at com.google.inject.internal.ProviderInternalFactory.provision(ProviderInternalFactory.java:81)
    [error]     at com.google.inject.internal.BoundProviderFactory.provision(BoundProviderFactory.java:72)
    [error]     at com.google.inject.internal.ProviderInternalFactory.circularGet(ProviderInternalFactory.java:61)
    [error]     at com.google.inject.internal.BoundProviderFactory.get(BoundProviderFactory.java:62)
    [error]     at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46)
    [error]     at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1103)
    [error]     at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
    [error]     at com.google.inject.internal.SingletonScope$1.get(SingletonScope.java:145)
    [error]     at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:41)
    [error]     at com.google.inject.internal.SingleParameterInjector.inject(SingleParameterInjector.java:38)
    [error]     at com.google.inject.internal.SingleParameterInjector.getAll(SingleParameterInjector.java:62)
    [error]     at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:104)
    [error]     at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:85)
    [error]     at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:267)
    [error]     at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46)
    [error]     at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1103)
    [error]     at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
    [error]     at com.google.inject.internal.SingletonScope$1.get(SingletonScope.java:145)
    [error]     at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:41)
    [error]     at com.google.inject.internal.FactoryProxy.get(FactoryProxy.java:56)
    [error]     at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46)
    [error]     at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1103)
    [error]     at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
    [error]     at com.google.inject.internal.SingletonScope$1.get(SingletonScope.java:145)
    [error]     at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:41)
    [error]     at com.google.inject.internal.InternalInjectorCreator$1.call(InternalInjectorCreator.java:205)
    [error]     at com.google.inject.internal.InternalInjectorCreator$1.call(InternalInjectorCreator.java:199)
    [error]     at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1092)
    [error]     at com.google.inject.internal.InternalInjectorCreator.loadEagerSingletons(InternalInjectorCreator.java:199)
    [error]     at com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:180)
    [error]     at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:110)
    [error]     at com.google.inject.Guice.createInjector(Guice.java:96)
    [error]     at com.google.inject.Guice.createInjector(Guice.java:84)
    [error]     at play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:181)
    [error]     at play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:123)
    [error]     at play.api.test.FakeApplication.<init>(Fakes.scala:209)
    [error]     at play.test.FakeApplication.<init>(FakeApplication.java:51)
    [error]     at play.test.Helpers.fakeApplication(Helpers.java:124)
    [error]     at play.test.WithApplication.provideFakeApplication(WithApplication.java:46)
    [error]     at play.test.WithApplication.provideApplication(WithApplication.java:33)
    [error]     at play.test.WithApplication.startPlay(WithApplication.java:51)
    [error]     ...
    [error] Caused by: java.lang.NullPointerException
    [error]     at play.db.ebean.DefaultEbeanConfig$EbeanConfigParser.parse(DefaultEbeanConfig.java:79)
    [error]     ... 78 more
    [error] Test ModelsTest.createAndRetrieveUser failed: java.lang.NullPointerException: null, took 4.979 sec
    [error]     at play.test.Helpers.stop(Helpers.java:376)
    [error]     at ModelsTest.stopApp(ModelsTest.java:58)
    [error]     ...
    [error] Failed: Total 1, Failed 1, Errors 0, Passed 0
    [error] Failed tests:
    [error]     ModelsTest
    [error] (test:testOnly) sbt.TestsFailedException: Tests unsuccessful

I just started learning play (but actually most of tutorials are outdated) and I have spent more time trying to configure it to run than actually coding. I guess I should look up another framework.

Upvotes: 0

Views: 717

Answers (1)

Anton Sarov
Anton Sarov

Reputation: 3748

You don't need to set up a whole database just for testing (you are free to, of course). Play relies strongly on In-Memory databases (e.g. during development) and you can utilize this also in your tests:

@Test
public void findById() {
    running(fakeApplication(inMemoryDatabase("test")), () -> {
        User bob = User.findById(21l);
        assertEquals("[email protected]", bob.email);
        assertEquals("admin", bob.login);
    });
}

On the other hand if you really want to test the database access code you can go as far as creating a Database test object:

Database database = Databases.createFrom(
        "com.mysql.jdbc.Driver",
        "jdbc:mysql://localhost/test"
);

Which again can be in-memory:

Database database = Databases.inMemory(
        "mydatabase",
        ImmutableMap.of(
                "MODE", "MYSQL"
        ),
        ImmutableMap.of(
                "logStatements", true
        )
);

Just don't forget to release the resources after the test:

@After
public void shutdownDatabase() {
    database.shutdown();
}

Upvotes: 0

Related Questions