2012-04-03

Scala + Guice + Gradle: Integration tests (Part 5)

Previously I showed you how to add to your Scala + Guice project JPA 2 implemented by EclipseLink. In this article I will show you how to integration test it using the specs library.

build.gradle

Below are the relevant part of your build.gradle file.
test { exclude "**/*IT.class" }

task integrationTest(type: Test, dependsOn: testClasses) { include "**/*IT.class" }

check.dependsOn integrationTest

dependencies {
    testCompile group: 'org.scala-tools.testing', name: 'specs_2.9.1', version: '1.6.9'
    testCompile group: 'junit', name: 'junit', version: '4.+'
}
(This obviously is not the complete file.)

We specified a new task called integrationTest which will run our integration tests. It will run during gradle build as well. gradle test alone will NOT run them.

Step by step - PersistenceLibraryRepositorySpecIT.scala

package me.m1key.audioliciousmigration.repository

import org.specs._
import org.specs.runner._
import org.junit.runner.RunWith
import me.m1key.audioliciousmigration.persistence.JpaPersistenceProvider
import me.m1key.audiolicious.domain.entities.Library
import java.util.Date

@RunWith(classOf[JUnitSuiteRunner])
class PersistenceLibraryRepositorySpecIT extends Specification with JUnit {

 val jpaPersistenceProvider = new JpaPersistenceProvider
 jpaPersistenceProvider.initialise
 val repository = new PersistenceLibraryRepository(jpaPersistenceProvider)
 val entityManager = jpaPersistenceProvider.getEntityManager

//...
This is the test declaration. It allows us to run the test as a JUnit test from the IDE. Notice that file name ends with ...IT.scala. This is how we differentiate integration tests.

Step by step - before

// ...
doBeforeSpec {
   deleteLibraries
 }
//...
This will run before the test (just once).

Step by step - test


 "Fetching latest library with no libraries" should {
    var library: Library = null

    doFirst {
     println("Preparing test 1...")
     deleteLibraries
     println("Test prepared. Libraries: %d".format(librariesCount))
    }

    "return None." in {
     entityManager.getTransaction().begin()
     repository.getLatestLibrary() mustBe None
     entityManager.getTransaction().commit()
    }

    doLast {
     println("Cleaning up...")
     deleteLibraries
     println("Cleaned up. Libraries: %d".format(librariesCount))
    }
 }
This is a test. Notice the BDD style. The assertion is this line: repository.getLatestLibrary() mustBe None. doFirst and doLast allow us to prepare the test and clean up.

Step by step - another test

 "Fetching library by UUID with three libraries" should {
    setSequential()
    var olderLibrary: Library = null
    var anotherOlderLibrary: Library = null
    var newerLibrary: Library = null

    doFirst {
     println("Preparing test 3...")
     deleteLibraries
     olderLibrary = insertLibrary
     Thread.sleep(1000)
     anotherOlderLibrary = insertLibrary
     Thread.sleep(1000)
     newerLibrary = insertLibrary
     println("Test prepared. Libraries: %d".format(librariesCount))
    }

    "return correct 1st library." in {
     entityManager.getTransaction().begin()
     val library = repository.getLibrary(olderLibrary.getUuid).get
     entityManager.getTransaction().commit()
     library mustBe olderLibrary
    }

    "return correct 2nd library." in {
     entityManager.getTransaction().begin()
     val library = repository.getLibrary(anotherOlderLibrary.getUuid).get
     entityManager.getTransaction().commit()
     library mustBe anotherOlderLibrary
    }

    "return correct 3rd library." in {
     entityManager.getTransaction().begin()
     val library = repository.getLibrary(newerLibrary.getUuid).get
     entityManager.getTransaction().commit()
     library mustBe newerLibrary
    }

    doLast {
     println("Cleaning up...")
     deleteLibraries
     println("Cleaned up. Libraries: %d".format(librariesCount))
    }
 }
setSequential allows us to keep variables (olderLibrary, anotherOlderLibrary, newerLibrary) in scope for all tests.

Step by step - final clean up

//...  
 doAfterSpec {
    deleteLibraries
 }
//...

You can see the whole source for this file here.

Final note

gradle build will NOT run tests that have already run since the last code change! If you want them to run again, use gradle clean build.

Download source code

Source code for this article can be obtained via GitHub. Please see the README file for building and running.

Scala + Guice + Gradle: JPA 2 & EclipseLink (Part 4)

Previously I showed you how to create a Singleton in Guice powered Scala project. In this article I will show you how you can (JPA 2) EclipseLink support.

This sample app is a console app, so we have to handle entity management ourselves.

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

<persistence-unit name="audioliciousPu">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>

<class>me.m1key.audiolicious.domain.entities.Library</class>
<class>me.m1key.audiolicious.domain.entities.Artist</class>
<class>me.m1key.audiolicious.domain.entities.Album</class>
<class>me.m1key.audiolicious.domain.entities.Song</class>
<class>me.m1key.audiolicious.domain.entities.Stat</class>
<class>me.m1key.audiolicious.domain.entities.Rating</class>

<properties>
<property name="eclipselink.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="eclipselink.jdbc.url"
value="jdbc:mysql://localhost:3306/audiolicious_test" />
<property name="eclipselink.jdbc.user" value="root" />
<property name="eclipselink.jdbc.password" value="" />
<property name="eclipselink.target-database" value="MYSQL" />
<property name="eclipselink.logging.level" value="OFF" />
<property name="eclipselink.orm.throw.exceptions" value="true" />
</properties>
</persistence-unit>
</persistence>

EntityManager

package me.m1key.audioliciousmigration.persistence
import javax.persistence.EntityManager
import javax.persistence.EntityManagerFactory
import javax.persistence.Persistence

class JpaPersistenceProvider extends PersistenceProvider {

 private var factory: EntityManagerFactory = _
 private var entityManager: EntityManager = _

 @Override
 def initialise: Unit = {
   factory = Persistence.createEntityManagerFactory("audioliciousPu")
   entityManager = factory.createEntityManager();

 }

 @Override
 def getEntityManager: EntityManager = {
   return entityManager
 }

 @Override
 def close: Unit = {
   entityManager.close();
   factory.close();
 }

}

Usage

val persistenceProvider = injector.getInstance(classOf[PersistenceProvider])
persistenceProvider.initialise
val entityManager = persistenceProvider.getEntityManager
entityManager.getTransaction().begin()

//...

entityManager.getTransaction().commit()
persistenceProvider.close

build.gradle

repositories {
    // ...
    mavenRepo name: "EclipseLink", url: "http://download.eclipse.org/rt/eclipselink/maven.repo/"
}

dependencies {
    compile group: 'me.m1key.audiolicious', name: 'audiolicious-domain-objects', version: '0.1.0-SNAPSHOT'
    compile group: 'org.eclipse.persistence', name: 'eclipselink', version: '2.3.0'
    compile group: 'org.eclipse.persistence', name: 'javax.persistence', version: '2.0.0'
    compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.18'
    // …
}
We needed to explicitly add EclipseLink specific repository.

Conclusion

I did not present any entities here because in my app they come from another Java powered project. In the next article I will show you how to integration test this code.

Download source code

Source code for this article can be obtained via GitHub. Please see the README file for building and running.

2012-04-02

Scala + Guice + Gradle: Singleton (Part 3)

In the previous part of this tutorial I explained how to use Guice in your Gradle + Scala project. In this short post I will build up on that and show you how to create a singleton scoped instance, as the default scope in Grails is new every time requested.

Singleton

This is the singleton to be class:
class PersistenceLibraryRepository
@Inject() (private val persistenceProvider: PersistenceProvider)
extends LibraryRepository {
// ...
}
Nothing special here!

As far as I know, you cannot use the @Singleton annotation, so this is how you make this class a singleton:

class AudioliciousMigrationModule extends AbstractModule {

 @Override
 protected def configure() {
 bind(classOf[LibraryRepository])
   .to(classOf[PersistenceLibraryRepository])
   .in(Scopes.SINGLETON)  }
}
Voila!

In Part 4 I will show you how to connect to a MySQL database using JPA 2 implemented by EclipseLink.

Download source code

Source code for this article can be obtained via GitHub.

2012-04-01

Scala + Guice + Gradle (Part 2)

In Part 1 of this tutorial I showed you how to create a Gradle based Scala project. Now I will show you how to use Guice.

Basic example

The abstraction that defines the contract:
package me.m1key.audioliciousmigration

trait AudioliciousImporter {

def importLibrary(libraryUuid: String): Unit

}
The implementation:
package me.m1key.audioliciousmigration.importer

import me.m1key.audioliciousmigration.AudioliciousImporter

private[audioliciousmigration]
class RelativeDataImporter extends AudioliciousImporter {

def importLibrary(libraryUuid: String): Unit = {
    println("Importing library [%s]...".format(libraryUuid));
    println("Library [%s] imported.".format(libraryUuid));
}

}
Note package level private access - the implementation is not visible from the outside.

Here we bind implementations to abstractions:

package me.m1key.audioliciousmigration
import com.google.inject.AbstractModule
import com.google.inject.Provides
import me.m1key.audioliciousmigration.importer.RelativeDataImporter

class AudioliciousMigrationModule extends AbstractModule {

@Override
protected def configure() {
    bind(classOf[AudioliciousImporter]).to(classOf[RelativeDataImporter])
}

}
Finally, the bootstrap:
package me.m1key.audioliciousmigration
import com.google.inject.Guice

object Launcher {

def main(args: Array[String]): Unit = {
    println("Audiolicious Importer")
  
    val injector = Guice.createInjector(new AudioliciousMigrationModule)
    val importer = injector.getInstance(classOf[AudioliciousImporter])
    importer.importLibrary("UUID")
  
    println("Bye.")
}

}
If you're new to Guice and you're confused, you can read more about it here.

In Part 3 I will show you how to create a singleton.

Download source code

Source code for this article can be obtained via GitHub.