package com.lordofthejars.nosqlunit.mongodb; import com.mongodb.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.client.model.IndexOptions; import com.mongodb.util.JSON; import org.bson.Document; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.ByteArrayInputStream; import java.io.UnsupportedEncodingException; import java.util.List; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class WhenMongoDbOperationsAreRequired { private static final String DATA = "" + "{" + "\"collection1\": " + " [" + " {\"id\":1,\"code\":\"JSON dataset\",}," + " {\"id\":2,\"code\":\"Another row\",}" + " ]," + "\"collection2\": " + " [" + " {\"id\":3,\"code\":\"JSON dataset 2\",}," + " {\"id\":4,\"code\":\"Another row 2\",}" + " ]" + "}"; private static final String DATA_SHARD = "" + "{" + "\"collection1\": {" + " \"shard-key-pattern\":[\"id\",\"code\"]," + " \"data\":" + " [" + " {\"id\":1,\"code\":\"JSON dataset\",}," + " {\"id\":2,\"code\":\"Another row\",}" + " ]" + " }" + "}"; private static final String DATA_INDEX = "" + "{" + "\"collection1\": {" + " \"indexes\": [\n" + " {\n" + " \"index\": {\"field\": 1}\n" + " }\n" + " ]," + " \"data\":" + " [" + " {\"id\":1,\"code\":\"JSON dataset\",}," + " {\"id\":2,\"code\":\"Another row\",}" + " ]" + " }" + "}"; private static final String DATA_INDEX_OPTIONS = "" + "{" + "\"collection1\": {" + " \"indexes\": [\n" + " {\n" + " \"index\": {\"field\": 1},\n" + " \"options\": {\"unique\":true} " + " }\n" + " ]," + " \"data\":" + " [" + " {\"id\":1,\"code\":\"JSON dataset\",}," + " {\"id\":2,\"code\":\"Another row\",}" + " ]" + " }" + "}"; private static final String[] EXPECTED_COLLECTION_1 = new String[] {"{ \"id\" : 1, \"code\" : \"JSON dataset\" }", "{ \"id\" : 2, \"code\" : \"Another row\" }"}; private static final String[] EXPECTED_COLLECTION_2 = new String[] {"{ \"id\" : 3, \"code\" : \"JSON dataset 2\" }", "{ \"id\" : 4, \"code\" : \"Another row 2\" }"}; @Mock private MongoClient mongo; @Mock private MongoDatabase db; @Mock private MongoDatabase dbAdmin; @Before public void setUp() { MockitoAnnotations.initMocks(this); when(mongo.getDatabase("admin")).thenReturn(dbAdmin); when(mongo.getDatabase("test")).thenReturn(db); } @Test public void insert_operation_with_indexes_should_add_data_and_indexes_into_collections() throws UnsupportedEncodingException { MongoCollection collection1 = mock(MongoCollection.class); when(db.getName()).thenReturn("test"); when(db.getCollection("collection1")).thenReturn(collection1); MongoOperation mongoOperation = new MongoOperation(mongo, new MongoDbConfiguration("localhost", "test")); mongoOperation.insert(new ByteArrayInputStream(DATA_INDEX.getBytes("UTF-8"))); verifyInsertedData(EXPECTED_COLLECTION_1, collection1); Document expectedIndex = new Document("field", 1); verifyIndexCreationCommand(expectedIndex, collection1); } @Test public void insert_operation_with_options_in_indexes_should_add_data_and_indexes_into_collections() throws UnsupportedEncodingException { MongoCollection collection1 = mock(MongoCollection.class); when(db.getName()).thenReturn("test"); when(db.getCollection("collection1")).thenReturn(collection1); MongoOperation mongoOperation = new MongoOperation(mongo, new MongoDbConfiguration("localhost", "test")); mongoOperation.insert(new ByteArrayInputStream(DATA_INDEX_OPTIONS.getBytes("UTF-8"))); verifyInsertedData(EXPECTED_COLLECTION_1, collection1); Document expectedIndex = new Document("field", 1); IndexOptions indexOptions = new IndexOptions(); indexOptions.unique(true); verifyIndexCreationCommandAndOptions(expectedIndex, indexOptions, collection1); } @Test public void insert_opertation_with_shards_should_add_data_into_collections() throws UnsupportedEncodingException { MongoCollection collection1 = mock(MongoCollection.class); MongoCollection collection2 = mock(MongoCollection.class); when(db.getName()).thenReturn("test"); when(db.getCollection("collection1")).thenReturn(collection1); when(db.getCollection("collection2")).thenReturn(collection2); MongoOperation mongoOperation = new MongoOperation(mongo, new MongoDbConfiguration("localhost", "test")); mongoOperation.insert(new ByteArrayInputStream(DATA_SHARD.getBytes("UTF-8"))); verifyInsertedData(EXPECTED_COLLECTION_1, collection1); verifyEnableShardingCommand("{ \"shardcollection\" : \"test.collection1\" , \"key\" : { \"id\" : 1 , \"code\" : 1}}", dbAdmin); } @Test public void insert_opertation_should_add_data_into_collections() throws UnsupportedEncodingException { MongoCollection collection1 = mock(MongoCollection.class); MongoCollection collection2 = mock(MongoCollection.class); when(db.getCollection("collection1")).thenReturn(collection1); when(db.getCollection("collection2")).thenReturn(collection2); MongoOperation mongoOperation = new MongoOperation(mongo, new MongoDbConfiguration("localhost", "test")); mongoOperation.insert(new ByteArrayInputStream(DATA.getBytes("UTF-8"))); verifyInsertedData(EXPECTED_COLLECTION_1, collection1); verifyInsertedData(EXPECTED_COLLECTION_2, collection2); } /*@Test public void same_data_on_compare_operation_should_assert_expected_data_with_inserted() { DBCollection collection1 = mock(DBCollection.class); DBCollection collection2 = mock(DBCollection.class); BasicDBObject value = new BasicDBObject(); when(collection1.findOne(anyObject())).thenReturn(eq(value)); //when(collection2.findOne(any(DBObject.class))).thenReturn(eq(value)); when(db.getCollection("collection1")).thenReturn(collection1); when(db.getCollection("collection2")).thenReturn(collection2); MongoOperation mongoOperation = new MongoOperation(mongo, new MongoDbConfiguration("test")); boolean equal = mongoOperation.compareExpectedData(DATA); assertThat(equal, is(true)); } @Test public void different_data_on_compare_operation_should_assert_expected_data_with_inserted() { DBCollection collection1 = mock(DBCollection.class); DBCollection collection2 = mock(DBCollection.class); when(db.getCollection("collection1")).thenReturn(collection1); when(db.getCollection("collection2")).thenReturn(collection2); when(collection1.findOne(any(DBObject.class))).thenReturn(null); when(collection2.findOne(any(DBObject.class))).thenReturn(eq(new BasicDBObject())); MongoOperation mongoOperation = new MongoOperation(mongo, new MongoDbConfiguration("test")); boolean equal = mongoOperation.compareExpectedData(DATA); assertThat(equal, is(false)); }*/ private void verifyIndexCreationCommand(Document indexDocument, MongoCollection collection) { final ArgumentCaptor<Document> indexCommandCaptor = ArgumentCaptor .forClass(Document.class); verify(collection, times(1)).createIndex(indexCommandCaptor.capture()); assertThat(indexCommandCaptor.getValue(), is(indexDocument)); } private void verifyIndexCreationCommandAndOptions(Document indexDocument, IndexOptions indexOptions, MongoCollection collection) { final ArgumentCaptor<Document> indexCommandCaptor = ArgumentCaptor .forClass(Document.class); final ArgumentCaptor<IndexOptions> indexOptionCommandCaptor = ArgumentCaptor .forClass(IndexOptions.class); verify(collection, times(1)).createIndex(indexCommandCaptor.capture(), indexOptionCommandCaptor.capture()); assertThat(indexCommandCaptor.getValue(), is(indexDocument)); assertThat(indexOptionCommandCaptor.getValue().isUnique(), is(indexOptions.isUnique())); } private void verifyEnableShardingCommand(String expectedCommand, MongoDatabase mockDb) { final ArgumentCaptor<Document> enableShardingCommandCaptor = ArgumentCaptor .forClass(Document.class); verify(mockDb, times(1)).runCommand(enableShardingCommandCaptor.capture()); Document command = enableShardingCommandCaptor.getValue(); String commandDocument = JSON.serialize(command); assertThat(commandDocument, is(expectedCommand)); } private void verifyInsertedData(String[] expectedData, MongoCollection mockCollection) { final ArgumentCaptor<Document> insertCaptor = ArgumentCaptor .forClass(Document.class); verify(mockCollection, times(2)).insertOne(insertCaptor.capture()); List<Document> allValues = insertCaptor.getAllValues(); for (int i = 0; i < expectedData.length; i++) { assertThat(allValues.get(i).toJson(), is(expectedData[i])); } } }