cayenne-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Juan José Gil <mat...@gmail.com>
Subject Re: Unit Testing cayenne apps
Date Sat, 27 Apr 2013 22:46:38 GMT
it worked!

by the way, i did this "extra coding", as I'm trying to learn TestNG too,
I'm using some niceties of it...
the tests are "statefull" so once the runtime is created, it is reused, but
with @AfterSuite it is shutdown after the last test :)

My base test class is defined as:

public abstract class MatecitoPersistenceTest {
    private static ServerRuntime cayenneRuntime;
    private ObjectContext objectContext;

    @AfterMethod public void shutdownTest() {
      if (objectContext != null) {
        objectContext.rollbackChanges();
        objectContext = null;
      }
    }

    @AfterSuite public void shutdownSuite() {
      if (cayenneRuntime != null) {
        cayenneRuntime.shutdown();
        cayenneRuntime = null;
      }
    }

    protected ServerRuntime getServerRuntime() {
      if (cayenneRuntime == null) {
        cayenneRuntime = createCayenneRuntime();
      }
      return cayenneRuntime;
    }

    protected ServerRuntime createCayenneRuntime() {
      return new ServerRuntime(cayenneConfig(), cayenneConfigModules());
    }

    protected abstract String cayenneConfig();

    protected abstract Module[] cayenneConfigModules();

    protected TestModule moduleOn(final String jdbcUrl) {
      return new TestModule(jdbcUrl);
    }

    protected ObjectContextProvider getObjectContextProvider() {
      return ObjectContextProvider.of(getObjectContext());
    }

    protected ObjectContext getObjectContext() {
      if (objectContext == null) {
        objectContext = createObjectContext();
      }
      return objectContext;
    }

    protected ObjectContext createObjectContext() {
      return getServerRuntime().getContext();
    }
}

this is my module definition utility:

public final class TestModule implements Module {
    private final Map<String, Object> jdbcProperties;

    TestModule(final String jdbcUrl) {
      jdbcProperties = new HashMap<>();
      jdbcProperties.put(Constants.JDBC_URL_PROPERTY, jdbcUrl);
    }

    public TestModule driver(final String jdbcDriverClassName) {
        jdbcProperties.put(Constants.JDBC_DRIVER_PROPERTY,
jdbcDriverClassName);
        return this;
    }

    public TestModule driver(final Class<? extends java.sql.Driver>
jdbcDriver) {
        return driver(jdbcDriver == null ? null : jdbcDriver.getName());
    }

    public TestModule user(final String username) {
        jdbcProperties.put(Constants.JDBC_USERNAME_PROPERTY, username);
        return this;
    }

    public TestModule password(final String password) {
        jdbcProperties.put(Constants.JDBC_PASSWORD_PROPERTY, password);
        return this;
    }

    public TestModule minConnections(final int value) {
        jdbcProperties.put(Constants.JDBC_MIN_CONNECTIONS_PROPERTY, value);
        return this;
    }

    public TestModule maxConnections(final int value) {
        jdbcProperties.put(Constants.JDBC_MAX_CONNECTIONS_PROPERTY, value);
        return this;
    }

    @Override public void configure(final Binder binder) {
        for (Map.Entry<String, Object> jdbcProperty :
jdbcProperties.entrySet())

binder.bindMap(Constants.PROPERTIES_MAP).put(jdbcProperty.getKey(),
jdbcProperty.getValue());
    }
}

so in my suites of tests I only have to define something like:

public abstract class PersistenceTest extends MatecitoPersistenceTest {
    @Override protected String cayenneConfig() { return
"db/cayenne-diglori.xml"; }

    @Override protected Module[] cayenneConfigModules() {
      return new Module[] {

moduleOn("jdbc:postgresql://localhost:5432/db_test").driver(org.postgresql.Driver.class).user("user").password("pass")
      };
    }
}

who says java can not be pretty? :P


2013/4/23 Matero <matero@gmail.com>

> That's awesome!
> I'll give it a try tonight and tell you how it was
>
> If I succeed with this approach, I'll blog about it to make a note to
> future me ;)
>
> Enviado desde mi iPad
>
> El 23/04/2013, a las 11:42, John Huss <johnthuss@gmail.com> escribió:
>
> > You can configure the database connection in 3.1 with a module like:
> >
> > import org.apache.cayenne.configuration.Constants;
> > import org.apache.cayenne.di.Binder;
> > import org.apache.cayenne.di.Module;
> >
> > public class AppModule implements Module {
> > public void configure(Binder binder) {
> > binder.bindMap(Constants.PROPERTIES_MAP).put(Constants.JDBC_URL_PROPERTY,
> > "jdbc:postgresql://localhost/mydb");
> >
> binder.bindMap(Constants.PROPERTIES_MAP).put(Constants.JDBC_DRIVER_PROPERTY,
> > org.postgresql.Driver.class.getName());
> > }
> >
> > }
> >
> > You just have to list your module when creating the ServerRuntime:
> >
> > CayenneRuntime runtime = new ServerRuntime("cayenne-MyDomain.xml", new
> > AppModule());
> >
> > It can also be specified in web.xml instead if you are using
> CayenneFilter
> > or something.
> >
> > The JDBC_URL_PROPERTY will override the url for all databases.  If you
> have
> > more than one you'll want to override each independently by appending the
> > domain name and dataNode name to the property name, like:
> >
> > binder.bindMap(Constants.PROPERTIES_MAP).put(Constants.JDBC_URL_PROPERTY
> +
> > ".MyDomain.MyDataNode", "jdbc:postgresql://localhost/mydb");
> >
> > The specific url value or driver value you are using doesn't have to be
> > hard coded.  You can read it from a file or from the system properties
> set
> > on the command line - whatever you want.
> >
> > John
> >
> >
> >
> > On Tue, Apr 23, 2013 at 7:05 AM, Juan José Gil <matero@gmail.com> wrote:
> >
> >> Hi, I'm using cayenne as persistence layer.
> >>
> >> The project is builded with maven and developed with Eclipse.
> >>
> >> The DB is migrated using flyway (http://flywaydb.org/) and I'm using
> >> different DBs config for:
> >>
> >> * production
> >> * development
> >> * testing
> >>
> >> So, for migrations, deployment, continuous integration and anything that
> >> relies on maven I'm using maven "filtering" capabilities to define the
> jdbc
> >> url of the database to be used.
> >>
> >> BUT when I'm working at eclipse, and try to run my tests / startup my
> >> webapp, I cant filter the project resources (not automatically at least)
> >> So currently I'm copy-pasting my cayenne conf from
> src/main/resources/db to
> >> src/test/resources/db... and I'm not happy with this solution, I feel it
> >> smelly, propense to failure, it's ugly, very ugly!
> >>
> >> I did try to only define the cayenne config at testing resources, but
> when
> >> I do that, it doesn't find the mapping xml.
> >>
> >> Is there a way con pass the mapping path instead of a mapping name to a
> >> cayenne config?
> >>
> >> Can someone point me what should be done to avoid this code/conf smell?
> >>
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message