Support MongoDB in unit tests. Added parameterized test, so ImportTest and AdapterTest work with both picketlink and mongo

This commit is contained in:
mposolda 2013-09-13 14:50:24 +02:00
parent 4db738689f
commit 68ed19f15d
12 changed files with 255 additions and 64 deletions

View file

@ -254,6 +254,11 @@
<artifactId>mongo-java-driver</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<version>1.27</version>
</dependency>
</dependencies>
</dependencyManagement>

View file

@ -152,6 +152,11 @@
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
</dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>

View file

@ -48,7 +48,7 @@ public class MongoDBImpl implements NoSQL {
new ConcurrentHashMap<Class<? extends NoSQLObject>, ObjectInfo>();
public MongoDBImpl(DB database, boolean removeAllObjectsAtStartup, Class<? extends NoSQLObject>[] managedDataTypes) {
public MongoDBImpl(DB database, boolean dropDatabaseOnStartup, Class<? extends NoSQLObject>[] managedDataTypes) {
this.database = database;
typeConverter = new TypeConverter();
@ -70,20 +70,9 @@ public class MongoDBImpl implements NoSQL {
typeConverter.addDBObjectConverter(new BasicDBObjectConverter(this, typeConverter, type));
}
if (removeAllObjectsAtStartup) {
for (Class<? extends NoSQLObject> type : managedDataTypes) {
ObjectInfo objectInfo = getObjectInfo(type);
String collectionName = objectInfo.getDbCollectionName();
if (collectionName != null) {
logger.debug("Dropping collection " + collectionName);
DBCollection dbCollection = this.database.getCollection(collectionName);
dbCollection.drop();
} else {
logger.debug("Skip removing objects of type " + type + " as it doesn't have it's own collection");
}
}
logger.info("All objects successfully removed from MongoDB");
if (dropDatabaseOnStartup) {
this.database.dropDatabase();
logger.info("Database " + this.database.getName() + " dropped in MongoDB");
}
}

View file

@ -43,14 +43,14 @@ public class MongoDBSessionFactory implements KeycloakSessionFactory {
private final MongoClient mongoClient;
private final NoSQL mongoDB;
public MongoDBSessionFactory(String host, int port, String dbName, boolean removeAllObjectsAtStartup) {
logger.info(String.format("Going to use MongoDB database. host: %s, port: %d, databaseName: %s, removeAllObjectsAtStartup: %b", host, port, dbName, removeAllObjectsAtStartup));
public MongoDBSessionFactory(String host, int port, String dbName, boolean dropDatabaseOnStartup) {
logger.info(String.format("Going to use MongoDB database. host: %s, port: %d, databaseName: %s, removeAllObjectsAtStartup: %b", host, port, dbName, dropDatabaseOnStartup));
try {
// TODO: authentication support
mongoClient = new MongoClient(host, port);
DB db = mongoClient.getDB(dbName);
mongoDB = new MongoDBImpl(db, removeAllObjectsAtStartup, MANAGED_DATA_TYPES);
mongoDB = new MongoDBImpl(db, dropDatabaseOnStartup, MANAGED_DATA_TYPES);
} catch (UnknownHostException e) {
throw new RuntimeException(e);

View file

@ -37,6 +37,16 @@ import java.util.Set;
* @version $Revision: 1 $
*/
public class KeycloakApplication extends Application {
public static final String SESSION_FACTORY = "keycloak.sessionFactory";
public static final String SESSION_FACTORY_PICKETLINK = "picketlink";
public static final String SESSION_FACTORY_MONGO = "mongo";
public static final String MONGO_HOST = "keycloak.mongodb.host";
public static final String MONGO_PORT = "keycloak.mongodb.port";
public static final String MONGO_DB_NAME = "keycloak.mongodb.databaseName";
public static final String MONGO_DROP_DB_ON_STARTUP = "keycloak.mongodb.dropDatabaseOnStartup";
protected Set<Object> singletons = new HashSet<Object>();
protected Set<Class<?>> classes = new HashSet<Class<?>>();
@ -62,8 +72,8 @@ public class KeycloakApplication extends Application {
}
public static KeycloakSessionFactory buildSessionFactory() {
String sessionFactoryType = System.getProperty("keycloak.sessionFactory", "picketlink");
if ("mongo".equals(sessionFactoryType)) {
String sessionFactoryType = System.getProperty(SESSION_FACTORY, SESSION_FACTORY_PICKETLINK);
if (SESSION_FACTORY_MONGO.equals(sessionFactoryType)) {
return buildMongoDBSessionFactory();
} else {
return buildPicketlinkSessionFactory();
@ -76,11 +86,11 @@ public class KeycloakApplication extends Application {
}
private static KeycloakSessionFactory buildMongoDBSessionFactory() {
String host = System.getProperty("keycloak.mongodb.host", "localhost");
int port = Integer.parseInt(System.getProperty("keycloak.mongodb.port", "27017"));
String dbName = System.getProperty("keycloak.mongodb.databaseName", "keycloak");
boolean removeAllObjectsOnStartup = Boolean.parseBoolean(System.getProperty("keycloak.mongodb.removeAllObjectsOnStartup", "true"));
return new MongoDBSessionFactory(host, port, dbName, removeAllObjectsOnStartup);
String host = System.getProperty(MONGO_HOST, "localhost");
int port = Integer.parseInt(System.getProperty(MONGO_PORT, "27017"));
String dbName = System.getProperty(MONGO_DB_NAME, "keycloak");
boolean dropDatabaseOnStartup = Boolean.parseBoolean(System.getProperty(MONGO_DROP_DB_ON_STARTUP, "true"));
return new MongoDBSessionFactory(host, port, dbName, dropDatabaseOnStartup);
}
public KeycloakSessionFactory getFactory() {

View file

@ -12,6 +12,8 @@ import org.keycloak.services.managers.OAuthClientManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.models.UserModel.RequiredAction;
import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.test.common.AbstractKeycloakTest;
import org.keycloak.test.common.SessionFactoryTestContext;
import java.util.HashSet;
@ -24,30 +26,16 @@ import java.util.StringTokenizer;
* @version $Revision: 1 $
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class AdapterTest {
private KeycloakSessionFactory factory;
private KeycloakSession identitySession;
private RealmManager adapter;
public class AdapterTest extends AbstractKeycloakTest {
private RealmModel realmModel;
@Before
public void before() throws Exception {
factory = KeycloakApplication.buildSessionFactory();
identitySession = factory.createSession();
identitySession.getTransaction().begin();
adapter = new RealmManager(identitySession);
}
@After
public void after() throws Exception {
identitySession.getTransaction().commit();
identitySession.close();
factory.close();
public AdapterTest(SessionFactoryTestContext testContext) {
super(testContext);
}
@Test
public void installTest() throws Exception {
new InstallationManager().install(adapter);
new InstallationManager().install(getRealmManager());
}
@ -63,7 +51,7 @@ public class AdapterTest {
@Test
public void test1CreateRealm() throws Exception {
realmModel = adapter.createRealm("JUGGLER");
realmModel = getRealmManager().createRealm("JUGGLER");
realmModel.setAccessCodeLifespan(100);
realmModel.setAccessCodeLifespanUserAction(600);
realmModel.setCookieLoginAllowed(true);
@ -76,7 +64,7 @@ public class AdapterTest {
realmModel.addDefaultRole("foo");
System.out.println(realmModel.getId());
realmModel = adapter.getRealm(realmModel.getId());
realmModel = getRealmManager().getRealm(realmModel.getId());
Assert.assertNotNull(realmModel);
Assert.assertEquals(realmModel.getAccessCodeLifespan(), 100);
Assert.assertEquals(600, realmModel.getAccessCodeLifespanUserAction());

View file

@ -19,6 +19,8 @@ import org.keycloak.models.SocialLinkModel;
import org.keycloak.models.UserModel;
import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.services.resources.SaasService;
import org.keycloak.test.common.AbstractKeycloakTest;
import org.keycloak.test.common.SessionFactoryTestContext;
import java.util.List;
import java.util.Set;
@ -28,29 +30,15 @@ import java.util.Set;
* @version $Revision: 1 $
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ImportTest {
private KeycloakSessionFactory factory;
private KeycloakSession identitySession;
private RealmManager manager;
private RealmModel realmModel;
public class ImportTest extends AbstractKeycloakTest {
@Before
public void before() throws Exception {
factory = KeycloakApplication.buildSessionFactory();
identitySession = factory.createSession();
identitySession.getTransaction().begin();
manager = new RealmManager(identitySession);
}
@After
public void after() throws Exception {
identitySession.getTransaction().commit();
identitySession.close();
factory.close();
public ImportTest(SessionFactoryTestContext testContext) {
super(testContext);
}
@Test
public void install() throws Exception {
RealmManager manager = getRealmManager();
RealmModel defaultRealm = manager.createRealm(RealmModel.DEFAULT_REALM, RealmModel.DEFAULT_REALM);
defaultRealm.setName(RealmModel.DEFAULT_REALM);
defaultRealm.setEnabled(true);
@ -93,7 +81,7 @@ public class ImportTest {
List<ApplicationModel> resources = realm.getApplications();
Assert.assertEquals(2, resources.size());
List<RealmModel> realms = identitySession.getRealms(admin);
List<RealmModel> realms = getIdentitySession().getRealms(admin);
Assert.assertEquals(1, realms.size());
// Test scope relationship
@ -129,6 +117,7 @@ public class ImportTest {
@Test
public void install2() throws Exception {
RealmManager manager = getRealmManager();
RealmModel defaultRealm = manager.createRealm(RealmModel.DEFAULT_REALM, RealmModel.DEFAULT_REALM);
defaultRealm.setName(RealmModel.DEFAULT_REALM);
defaultRealm.setEnabled(true);

View file

@ -11,6 +11,11 @@ import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.services.models.KeycloakSession;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.test.common.AbstractKeycloakTest;
import org.keycloak.test.common.SessionFactoryTestContext;
import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.client.Entity;

View file

@ -0,0 +1,96 @@
package org.keycloak.test.common;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.models.KeycloakSession;
import org.keycloak.services.models.KeycloakSessionFactory;
import org.keycloak.services.resources.KeycloakApplication;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@RunWith(Parameterized.class)
public abstract class AbstractKeycloakTest {
protected static final SessionFactoryTestContext[] TEST_CONTEXTS;
private final SessionFactoryTestContext testContext;
private KeycloakSessionFactory factory;
private KeycloakSession identitySession;
private RealmManager realmManager;
// STATIC METHODS
static
{
// TODO: Disable MongoDB by default and enable it just for some specific maven profile (system property)?
TEST_CONTEXTS = new SessionFactoryTestContext[] {
new PicketlinkSessionFactoryTestContext(),
new MongoDBSessionFactoryTestContext()
};
}
@Parameterized.Parameters
public static Iterable<Object[]> parameters() {
List<Object[]> params = new ArrayList<Object[]>();
for (SessionFactoryTestContext testContext : TEST_CONTEXTS) {
params.add(new Object[] {testContext});
}
return params;
}
@BeforeClass
public static void baseBeforeClass() {
for (SessionFactoryTestContext testContext : TEST_CONTEXTS) {
testContext.beforeTestClass();
}
}
@AfterClass
public static void baseAfterClass() {
for (SessionFactoryTestContext testContext : TEST_CONTEXTS) {
testContext.afterTestClass();
}
}
// NON-STATIC METHODS
public AbstractKeycloakTest(SessionFactoryTestContext testContext) {
this.testContext = testContext;
}
@Before
public void before() throws Exception {
testContext.initEnvironment();
factory = KeycloakApplication.buildSessionFactory();
identitySession = factory.createSession();
identitySession.getTransaction().begin();
realmManager = new RealmManager(identitySession);
}
@After
public void after() throws Exception {
identitySession.getTransaction().commit();
identitySession.close();
factory.close();
}
protected RealmManager getRealmManager() {
return realmManager;
}
protected KeycloakSession getIdentitySession() {
return identitySession;
}
}

View file

@ -0,0 +1,60 @@
package org.keycloak.test.common;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import de.flapdoodle.embed.mongo.MongodExecutable;
import de.flapdoodle.embed.mongo.MongodProcess;
import de.flapdoodle.embed.mongo.MongodStarter;
import de.flapdoodle.embed.mongo.config.MongodConfig;
import de.flapdoodle.embed.mongo.distribution.Version;
import de.flapdoodle.embed.process.runtime.Network;
import org.jboss.resteasy.logging.Logger;
import org.keycloak.services.models.KeycloakSessionFactory;
import org.keycloak.services.resources.KeycloakApplication;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class MongoDBSessionFactoryTestContext implements SessionFactoryTestContext {
protected static final Logger logger = Logger.getLogger(MongoDBSessionFactoryTestContext.class);
private static final int PORT = 27777;
private MongodExecutable mongodExe;
private MongodProcess mongod;
@Override
public void beforeTestClass() {
logger.info("Bootstrapping MongoDB on localhost, port " + PORT);
try {
mongodExe = MongodStarter.getDefaultInstance().prepare(new MongodConfig(Version.V2_0_5, PORT, Network.localhostIsIPv6()));
mongod = mongodExe.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
logger.info("MongoDB bootstrapped successfully");
}
@Override
public void afterTestClass() {
if (mongodExe != null) {
if (mongod != null) {
mongod.stop();
}
mongodExe.stop();
}
logger.info("MongoDB stopped successfully");
// Null this, so other tests are not affected
System.setProperty(KeycloakApplication.SESSION_FACTORY, "");
}
@Override
public void initEnvironment() {
System.setProperty(KeycloakApplication.SESSION_FACTORY, KeycloakApplication.SESSION_FACTORY_MONGO);
System.setProperty(KeycloakApplication.MONGO_HOST, "localhost");
System.setProperty(KeycloakApplication.MONGO_PORT, String.valueOf(PORT));
System.setProperty(KeycloakApplication.MONGO_DB_NAME, "keycloakTest");
System.setProperty(KeycloakApplication.MONGO_DROP_DB_ON_STARTUP, "true");
}
}

View file

@ -0,0 +1,25 @@
package org.keycloak.test.common;
import org.keycloak.services.models.KeycloakSessionFactory;
import org.keycloak.services.resources.KeycloakApplication;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class PicketlinkSessionFactoryTestContext implements SessionFactoryTestContext {
@Override
public void beforeTestClass() {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void afterTestClass() {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void initEnvironment() {
System.setProperty(KeycloakApplication.SESSION_FACTORY, KeycloakApplication.SESSION_FACTORY_PICKETLINK);
}
}

View file

@ -0,0 +1,19 @@
package org.keycloak.test.common;
import org.keycloak.services.models.KeycloakSessionFactory;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface SessionFactoryTestContext {
void beforeTestClass();
void afterTestClass();
/**
* Init system properties (or other configuration) to ensure that KeycloakApplication.buildSessionFactory() will return correct
* instance of KeycloakSessionFactory for our test
*/
void initEnvironment();
}