diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml
index 25453a791..6385b11bd 100644
--- a/spring-data-mongodb/pom.xml
+++ b/spring-data-mongodb/pom.xml
@@ -2,7 +2,7 @@
4.0.0
-
+
spring-data-mongodb
Spring Data MongoDB - Core
@@ -21,7 +21,7 @@
-
+
org.springframework
@@ -77,7 +77,7 @@
1.0
true
-
+
javax.enterprise
@@ -86,21 +86,21 @@
provided
true
-
+
javax.el
el-api
${cdi}
test
-
+
org.apache.openwebbeans.test
cditest-owb
${webbeans}
test
-
+
javax.servlet
servlet-api
@@ -115,7 +115,7 @@
${validation}
true
-
+
org.objenesis
objenesis
@@ -129,23 +129,23 @@
4.2.0.Final
test
-
+
joda-time
joda-time
${jodatime}
test
-
+
org.slf4j
jul-to-slf4j
${slf4j}
test
-
+
-
+
@@ -189,9 +189,14 @@
src/test/resources/logging.properties
+
+
+ listener
+ org.springframework.data.mongodb.test.util.CleanMongoDBJunitRunListener
+
+
-
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDB.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDB.java
new file mode 100644
index 000000000..953f4b1bf
--- /dev/null
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDB.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.mongodb.test.util;
+
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.CollectionUtils;
+
+import com.mongodb.DB;
+import com.mongodb.MongoClient;
+
+/**
+ * @author Christoph Strobl
+ */
+public class CleanMongoDB implements TestRule {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CleanMongoDB.class);
+
+ public enum Types {
+ DATABASE, COLLECTION, INDEX;
+ }
+
+ private Set preserveDatabases = new HashSet() {
+
+ private static final long serialVersionUID = -8698807376808700046L;
+
+ {
+ add("admin");
+ add("local");
+ }
+ };
+
+ private Set dbNames = new HashSet();
+ private Set collectionNames = new HashSet();
+ private Set types = new HashSet();
+ private MongoClient client;
+
+ public CleanMongoDB() {
+ this(null);
+ }
+
+ public CleanMongoDB(String host, int port) throws UnknownHostException {
+ this(new MongoClient(host, port));
+ }
+
+ public CleanMongoDB(MongoClient client) {
+ this.client = client;
+ }
+
+ public static CleanMongoDB everything() {
+
+ CleanMongoDB cleanMongoDB = new CleanMongoDB();
+ cleanMongoDB.clean(Types.DATABASE);
+ return cleanMongoDB;
+ }
+
+ public static CleanMongoDB databases(String... dbNames) {
+
+ CleanMongoDB cleanMongoDB = new CleanMongoDB();
+ cleanMongoDB.clean(Types.DATABASE);
+ cleanMongoDB.collectionNames.addAll(Arrays.asList(dbNames));
+ return cleanMongoDB;
+ }
+
+ public static CleanMongoDB indexes() {
+
+ CleanMongoDB cleanMongoDB = new CleanMongoDB();
+ cleanMongoDB.clean(Types.INDEX);
+ return cleanMongoDB;
+ }
+
+ public CleanMongoDB clean(Types... types) {
+
+ this.types.addAll(Arrays.asList(types));
+ return this;
+ }
+
+ public Statement apply() {
+ return apply(null, null);
+ }
+
+ public Statement apply(Statement base, Description description) {
+ return new MongoCleanStatement(base);
+ }
+
+ private class MongoCleanStatement extends Statement {
+
+ private final Statement base;
+
+ public MongoCleanStatement(Statement base) {
+ this.base = base;
+ }
+
+ @Override
+ public void evaluate() throws Throwable {
+
+ if (base != null) {
+ base.evaluate();
+ }
+
+ boolean isInternal = false;
+ if (client == null) {
+ client = new MongoClient();
+ isInternal = true;
+ }
+
+ Collection dbNamesToUse = dbNames;
+ if (dbNamesToUse.isEmpty()) {
+ dbNamesToUse = client.getDatabaseNames();
+ }
+
+ for (String dbName : dbNamesToUse) {
+
+ if (preserveDatabases.contains(dbName.toLowerCase())) {
+ continue;
+ }
+
+ if (types.contains(Types.DATABASE)) {
+ client.dropDatabase(dbName);
+ LOGGER.debug("Dropping DB '{}'. ", dbName);
+ }
+
+ if (types.contains(Types.COLLECTION)) {
+
+ DB db = client.getDB(dbName);
+ Collection collectionsToUse = initCollectionNames(db);
+ for (String collectionName : collectionsToUse) {
+ if (db.collectionExists(collectionName)) {
+ db.getCollectionFromString(collectionName).drop();
+ LOGGER.debug("Dropping collection '{}' for DB '{}'. ", collectionName, dbName);
+ }
+ }
+ }
+
+ if (types.contains(Types.INDEX)) {
+
+ DB db = client.getDB(dbName);
+ Collection collectionsToUse = initCollectionNames(db);
+ for (String collectionName : collectionsToUse) {
+ if (db.collectionExists(collectionName)) {
+ db.getCollectionFromString(collectionName).dropIndexes();
+ LOGGER.debug("Dropping indexes in collection '{}' for DB '{}'. ", collectionName, dbName);
+ }
+ }
+ }
+ }
+
+ if (isInternal) {
+ client.close();
+ client = null;
+ }
+ }
+
+ private Collection initCollectionNames(DB db) {
+
+ Collection collectionsToUse = collectionNames;
+ if (CollectionUtils.isEmpty(collectionsToUse)) {
+ collectionsToUse = db.getCollectionNames();
+ }
+ return collectionsToUse;
+ }
+ }
+
+}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDBJunitRunListener.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDBJunitRunListener.java
new file mode 100644
index 000000000..a5f0e90ef
--- /dev/null
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDBJunitRunListener.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.mongodb.test.util;
+
+import org.junit.runner.Result;
+import org.junit.runner.notification.RunListener;
+import org.springframework.data.mongodb.test.util.CleanMongoDB.Types;
+
+/**
+ * @author Christoph Strobl
+ */
+public class CleanMongoDBJunitRunListener extends RunListener {
+
+ @Override
+ public void testRunFinished(Result result) throws Exception {
+ super.testRunFinished(result);
+ try {
+ new CleanMongoDB().clean(Types.INDEX).apply().evaluate();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDBTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDBTests.java
new file mode 100644
index 000000000..5b600e905
--- /dev/null
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/CleanMongoDBTests.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.mongodb.test.util;
+
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.junit.runners.model.Statement;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.springframework.data.mongodb.test.util.CleanMongoDB.Types;
+
+import com.mongodb.DB;
+import com.mongodb.DBCollection;
+import com.mongodb.MongoClient;
+
+/**
+ * @author Christoph Strobl
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class CleanMongoDBTests {
+
+ private CleanMongoDB cleaner;
+ private @Mock Statement baseStatementMock;
+ private @Mock Description descriptionMock;
+ private @Mock MongoClient mongoClientMock;
+ private @Mock DB db1mock;
+ private @Mock DB db2mock;
+ private @Mock DBCollection collection1mock;
+
+ @Before
+ public void setUp() {
+
+ when(mongoClientMock.getDatabaseNames()).thenReturn(Arrays.asList("admin", "db1", "db2"));
+ when(mongoClientMock.getDB(eq("db1"))).thenReturn(db1mock);
+ when(mongoClientMock.getDB(eq("db2"))).thenReturn(db2mock);
+ when(db1mock.collectionExists(anyString())).thenReturn(true);
+ when(db2mock.collectionExists(anyString())).thenReturn(true);
+ when(db1mock.getCollectionNames()).thenReturn(Collections.singleton("collection-1"));
+ when(db2mock.getCollectionNames()).thenReturn(Collections. emptySet());
+ when(db1mock.getCollectionFromString(eq("collection-1"))).thenReturn(collection1mock);
+
+ cleaner = new CleanMongoDB(mongoClientMock);
+ }
+
+ @Test
+ public void preservesSystemCollectionsCorrectly() throws Throwable {
+
+ cleaner.clean(Types.DATABASE);
+
+ cleaner.apply(baseStatementMock, descriptionMock).evaluate();
+
+ verify(mongoClientMock, times(1)).dropDatabase(eq("db1"));
+ verify(mongoClientMock, times(1)).dropDatabase(eq("db2"));
+ verify(mongoClientMock, never()).dropDatabase(eq("admin"));
+ }
+
+ @Test
+ public void removesCollectionsCorrectly() throws Throwable {
+
+ cleaner.clean(Types.COLLECTION);
+
+ cleaner.apply(baseStatementMock, descriptionMock).evaluate();
+
+ verify(mongoClientMock, never()).dropDatabase(eq("db1"));
+ verify(mongoClientMock, never()).dropDatabase(eq("db2"));
+ verify(mongoClientMock, never()).dropDatabase(eq("admin"));
+
+ verify(collection1mock, times(1)).drop();
+ }
+
+ @Test
+ public void removesIndexesCorrectly() throws Throwable {
+
+ cleaner.clean(Types.INDEX);
+
+ cleaner.apply(baseStatementMock, descriptionMock).evaluate();
+
+ verify(mongoClientMock, never()).dropDatabase(eq("db1"));
+ verify(mongoClientMock, never()).dropDatabase(eq("db2"));
+ verify(mongoClientMock, never()).dropDatabase(eq("admin"));
+
+ verify(collection1mock, times(1)).dropIndexes();
+ }
+}