/mongodb/src/test/java/org/hibernate/ogm/datastore/mongodb/utils/MockMongoClientBuilder.java

https://github.com/hibernate/hibernate-ogm · Java · 148 lines · 83 code · 22 blank · 43 comment · 2 complexity · a5458e0300fc4cc56a94c0934cffddac MD5 · raw file

  1. /*
  2. * Hibernate OGM, Domain model persistence for NoSQL datastores
  3. *
  4. * License: GNU Lesser General Public License (LGPL), version 2.1 or later
  5. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
  6. */
  7. package org.hibernate.ogm.datastore.mongodb.utils;
  8. import static org.mockito.Matchers.any;
  9. import static org.mockito.Matchers.anyString;
  10. import static org.mockito.Mockito.mock;
  11. import static org.mockito.Mockito.when;
  12. import java.util.HashMap;
  13. import java.util.Map;
  14. import java.util.Map.Entry;
  15. import com.mongodb.MongoClient;
  16. import com.mongodb.ReadConcern;
  17. import com.mongodb.ReadPreference;
  18. import com.mongodb.WriteConcern;
  19. import com.mongodb.client.FindIterable;
  20. import com.mongodb.client.MongoCollection;
  21. import com.mongodb.client.MongoCursor;
  22. import com.mongodb.client.MongoDatabase;
  23. import com.mongodb.client.MongoIterable;
  24. import com.mongodb.client.model.FindOneAndUpdateOptions;
  25. import com.mongodb.client.result.DeleteResult;
  26. import org.bson.Document;
  27. /**
  28. * A builder for mocked {@link MongoClient} instances which return given {@link Document}s for given collections.
  29. * <p>
  30. * Note that currently only one {@code Document} is allowed per collection, but this could be expanded into a more
  31. * general mechanism if required.
  32. *
  33. * @author Gunnar Morling
  34. */
  35. public class MockMongoClientBuilder {
  36. /**
  37. * Builds an new mock MongoDB client.
  38. *
  39. * @return a builder context following the fluent invocation pattern.
  40. */
  41. public static MockMongoClientBuilderContext mockClient() {
  42. return new MockMongoClientBuilderContext();
  43. }
  44. public static class MockMongoClientBuilderContext {
  45. private final Map<String, MongoCollection<Document>> collections = new HashMap<>();
  46. /**
  47. * Registers the given {@link Document} with the specified collection. The object can be retrieved from the
  48. * collection via {@link MongoCollection<Document>#findOne(Document, Document))}.
  49. * <p>
  50. * Note that currently only one {@code Document} is supported per collection, but this could be expanded into a
  51. * more general mechanism if required.
  52. */
  53. public MockMongoClientBuilderContext insert(String collectionName, Document object) {
  54. MongoCollection<Document> collection = mock( MongoCollection.class );
  55. when( collection.withWriteConcern( any( WriteConcern.class ) ) ).thenReturn( collection );
  56. when( collection.withReadConcern( any( ReadConcern.class ) ) ).thenReturn( collection );
  57. when( collection.withReadPreference( any( ReadPreference.class ) ) ).thenReturn( collection );
  58. collections.put( collectionName, collection );
  59. FindIterable<Document> findIterableMock1 = mock( FindIterable.class );
  60. FindIterable<Document> findIterableMock2 = mock( FindIterable.class );
  61. when( findIterableMock1.projection( any( Document.class ) ) ).thenReturn( findIterableMock2 );
  62. when( findIterableMock1.modifiers( any( Document.class ) ) ).thenReturn( findIterableMock1 );
  63. when( findIterableMock2.first() ).thenReturn( object );
  64. when( collection.find( any( Document.class ) ) ).thenReturn( findIterableMock1 );
  65. when( collection.findOneAndUpdate( any( Document.class ), any( Document.class ), any( FindOneAndUpdateOptions.class ) ) ).thenReturn( object );
  66. DeleteResult deleteResult = mock( DeleteResult.class );
  67. when( collection.deleteMany( any( Document.class ) ) ).thenReturn( deleteResult );
  68. return this;
  69. }
  70. /**
  71. * Builds and returns a mock MongoDB client based on the given configuration.
  72. * @see <a href="https://jaihirsch.github.io/straw-in-a-haystack/mongodb/2016/07/25/mocking-the-mongodb-java-driver/">MongoDb Driver mocking</a>
  73. */
  74. public MockMongoClient build() {
  75. MongoDatabase database = mock( MongoDatabase.class );
  76. MongoCollection<Document> defaultCollection = mock( MongoCollection.class );
  77. when( defaultCollection.withWriteConcern( any( WriteConcern.class ) ) ).thenReturn( defaultCollection );
  78. when( database.getCollection( anyString() ) ).thenReturn( defaultCollection );
  79. when( defaultCollection.withWriteConcern( any( WriteConcern.class ) ) ).thenReturn( defaultCollection );
  80. when( defaultCollection.withReadConcern( any( ReadConcern.class ) ) ).thenReturn( defaultCollection );
  81. when( defaultCollection.withReadPreference( any( ReadPreference.class ) ) ).thenReturn( defaultCollection );
  82. for ( Entry<String, MongoCollection<Document>> collection : collections.entrySet() ) {
  83. when( database.getCollection( collection.getKey() ) ).thenReturn( collection.getValue() );
  84. }
  85. MongoClient mongoClient = mock( MongoClient.class );
  86. MongoIterable<String> iterable = mock( MongoIterable.class );
  87. MongoCursor<String> cursor = mock( MongoCursor.class );
  88. when( iterable.iterator() ).thenReturn( cursor );
  89. when( cursor.hasNext() ).thenReturn( true ).thenReturn( false );
  90. when( cursor.next() ).thenReturn( "testdb" );
  91. //@TODO prepare mock for MongoCursor
  92. when( mongoClient.listDatabaseNames() ).thenReturn( iterable );
  93. when( mongoClient.getDatabase( anyString() ) ).thenReturn( database );
  94. return new MockMongoClient( collections, defaultCollection, mongoClient );
  95. }
  96. }
  97. /**
  98. * A mock client for MongoDB.
  99. *
  100. * @author Gunnar Morling
  101. */
  102. public static class MockMongoClient {
  103. private final Map<String, MongoCollection<Document>> collections;
  104. private final MongoCollection<Document> defaultCollection;
  105. private final MongoClient client;
  106. public MockMongoClient(Map<String, MongoCollection<Document>> collections, MongoCollection<Document> defaultCollection, MongoClient client) {
  107. this.collections = collections;
  108. this.defaultCollection = defaultCollection;
  109. this.client = client;
  110. }
  111. /**
  112. * Returns a mock {@link MongoClient}.
  113. */
  114. public MongoClient getClient() {
  115. return client;
  116. }
  117. /**
  118. * Returns the collection with a given name. This is a Mockito mock object, so verifications can be performed on
  119. * it.
  120. */
  121. public MongoCollection<Document> getCollection(String collectionName) {
  122. MongoCollection<Document> collection = collections.get( collectionName );
  123. return collection != null ? collection : defaultCollection;
  124. }
  125. }
  126. }