Karate Clients - MongoDB

Java Client to interact with MongoDB from karate.

It provides features to execute operations such as count, find, insert and insertMany, replace, delete and deleteMany over MongoDB collections.

mongodb

POM Configuration

POM Karate Tools

If the project has been generated using the Karate Tools Archetype the pom will already contain the corresponding configuration.
Add the karatetools dependency in the karate pom:
<properties>
  ...
  <!-- Karate Tools -->
  <karatetools.version>X.X.X</karatetools.version>
</properties>

<dependencies>
  ...
  <!-- Karate Tools -->
  <dependency>
    <groupId>dev.inditex.karate</groupId>
    <artifactId>karatetools-starter</artifactId>
    <version>${karatetools.version}</version>
    <scope>test</scope>
  </dependency>
</dependencies>

POM Driver

karatetools-starter already includes the corresponding MongoDB dependency.

If you need to change the dependency version, you can include it in the pom as follows:
  <properties>
    ...
    <!-- Karate Clients -->
    <!-- Karate Clients - MongoDB -->
    <mongodb-driver-sync.version>X.X.X</mongodb-driver-sync.version>
  </properties>

  <dependencies>
    ...
    <!-- Karate Clients -->
    <!-- Karate Clients - MongoDB -->
    <dependency>
      <groupId>org.mongodb</groupId>
      <artifactId>mongodb-driver-sync</artifactId>
      <version>${mongodb-driver-sync.version}</version>
    </dependency>
  </dependencies>

Client Configuration

Configuration parameters for the MongoDB clients. These values can be overwritten by the corresponding (DB specific) system properties. System properties can be injected by CI/CD.

If the project has been generated using the Karate Tools Archetype the archetype would have prompted for the creation of the configuration files.

This client can be configured for multi-environment execution with a config file per environment:

\---src
    \---test
        \---resources
            \---config
                \---db
                    mongodb-config-local.yml
                    ...
                    mongodb-config-pre.yml

MongoDB Client Configuration Properties

⚙️ hosts: comma separated host names

⚙️ port: mongodb port

⚙️ db-name: database name

⚙️ user: user name to connect

⚙️ password: password to connect

⚙️ connect-timeout: number of milliseconds the driver will wait before a new connection attempt is aborted

⚙️ server-selection-timeout: number of milliseconds the mongo driver will wait to select a server for an operation before giving up and raising an error

⚙️ socket-timeout: number of milliseconds a send or receive on a socket can take before timeout

Example
# docker-compose environment variables:  <MONGO_INITDB_ROOT_USERNAME> <MONGO_INITDB_ROOT_PASSWORD>
# docker-compose folder structure:       mongo/<DB_NAME>/data
hosts: localhost
port: 27017
db-name: KARATE
user: karate
password: karate-pwd
connect-timeout: 10000
server-selection-timeout: 10000
socket-timeout: 10000

Client Features and Usage

Instantiate MongoDBClient

New instance of the MongoDBClient providing the configuration as a map loaded from a yaml file.

Java Signature
public MongoDBClient(final Map<Object, Object> configMap)
Gherkin Usage
# public MongoDBClient(final Map<Object, Object> configMap)
# Instantiate MongoDBClient
Given def config = read('classpath:config/db/mongodb-config-' + karate.env + '.yml')
Given def MongoDBClient = Java.type('dev.inditex.karate.mongodb.MongoDBClient')
Given def mongoDBClient = new MongoDBClient(config)

Check if MongoBD is available

Checks if the MongoBD connection can be established

Returns true is connection is available, false otherwise

Java Signature
public Boolean available()
Gherkin Usage
# public Boolean available()
When def available = mongoDBClient.available()
Then if (!available) karate.fail('MongoDB Client not available')

Count documents in a collection

Counts the number of documents in the collection

Java Signature
public Long count(final String collectionName)
Gherkin Usage
# Define collection
Given def collection = "data"

# public Long count(final String collectionName)
When def count = mongoDBClient.count(collection)
Then karate.log('mongoDBClient.count(',collection,')=', count)
Then assert count >= 0

Delete One document in a collection matching a filter

Removes one document from the collection that matches the given filter. If no documents match, the collection is not modified.

Deletes the first document that matches the filter. Use a field that is part of a unique index such as _id for precise deletions.

Returns the number of documents deleted (1 or 0)

Java Signature
public long delete(final String collectionName, final Map<String, Object> value)
Gherkin Usage
# Define collection
Given def collection = "data"

# Define Filters
Given def oneFilter = { "_id": "1" }

When def deleteOne = mongoDBClient.delete(collection, oneFilter)
Then karate.log('mongoDBClient.delete(',collection,', ', oneFilter, ')=', deleteOne)
Then assert deleteOne == 1
Then def countAfterDeleteOne = mongoDBClient.count(collection)
Then karate.log('mongoDBClient.count(',collection,')=', countAfterDeleteOne)
Then assert countAfterDeleteOne == 2

Delete Many documents in a collection matching a filter

Removes all documents from the collection that match the given query filter. If no documents match, the collection is not modified.

Returns the number of documents deleted

Java Signature
public long deleteMany(final String collectionName, final Map<String, Object> filter)
Gherkin Usage
# Define collection
Given def collection = "data"

# Define Filters
Given def manyFilter = { "name": { "$regex": "^karate-(.*)" } }

When def deletedMany = mongoDBClient.deleteMany(collection, manyFilter)
Then karate.log('mongoDBClient.delete(',collection,', ', manyFilter, ')=', deletedMany)
Then assert deletedMany >= 0
When def countAfterDeleteMany = mongoDBClient.count(collection)
Then karate.log('mongoDBClient.count(',collection,')=', countAfterDeleteMany)
Then assert countAfterDeleteMany == 0

Find all documents in a collection

Finds all documents in the collection.

Returns a JSON Array representing the obtained find result, where each row is a map << field name, Result value >>

For example:

[
  { "_id": 1, "name": "karate-01", "value": 1 },
  { "_id": 2, "name": "karate-02", "value": 2 },
  { "_id": 3, "name": "karate-03", "value": 3 }
]
Java Signature
public List<Map<String, Object>> find(final String collectionName)
Gherkin Usage
# Define collection
Given def collection = "data"

When def findAll = mongoDBClient.find(collection)
Then karate.log('mongoDBClient.find(',collection,')=', findAll.length )
Then assert findAll.length == 3
Then def result = karate.sort(findAll, x => x._id)
Then match result[0]._id == '1'
Then match result[0].name == 'karate-01'
Then match result[0].value == 1
Then match result[1]._id == '2'
Then match result[1].name == 'karate-02'
Then match result[1].value == 2
Then match result[2]._id == '3'
Then match result[2].name == 'karate-03'
Then match result[2].value == 3

Find documents in a collection matching a filter

Finds all documents in the collection matching the query filter

Returns a JSON Array representing the obtained find result, where each row is a map << field name, Result value >>

For example:

With a filter where id > 1:

{ "value": { $gt: 1 } }

will return:

[
  { "_id": 2, "name": "karate-02", "value": 2 },
  { "_id": 3, "name": "karate-03", "value": 3 }
]
Java Signature
public List<Map<String, Object>> find(final String collectionName, final Map<String, Object> filter)
Gherkin Usage - Find One
# Define collection
Given def collection = "data"

# Define Filters
Given def oneFilter = { "_id": "1" }

# public List<Map<String, Object>> find(final String collectionName, final Map<String, Object> filter)
When def findOne = mongoDBClient.find(collection, oneFilter)
Then karate.log('mongoDBClient.find(',collection,',', oneFilter, ')=', findOne.length )
Then assert findOne.length == 1
Then match findOne[0]._id == '1'
Then match findOne[0].name == 'karate-01'
Then match findOne[0].value == 1
Gherkin Usage - Find Some
# Define collection
Given def collection = "data"

# Define Filters
Given def someFilter = { "value": { $gt: 1 } }

When def findSome = mongoDBClient.find(collection, someFilter)
Then karate.log('mongoDBClient.find(',collection,',', someFilter, ')=', findSome.length )
Then assert findSome.length == 2
Then def result = karate.sort(findSome, x => x._id)
Then match result[0]._id == '2'
Then match result[0].name == 'karate-02'
Then match result[0].value == 2
Then match result[1]._id == '3'
Then match result[1].name == 'karate-03'
Then match result[1].value == 3

Insert One Document in a collection

Inserts the provided document in the collection.

Java Signature
public void insert(final String collectionName, final Map<String, Object> value)
Gherkin Usage
# Define collection
Given def collection = "data"

# Define Data
Given def oneDocument = { "_id": "1", "name": "karate-01", "value": 1 }

# public void insert(final String collectionName, final Map<String, Object> value)
# insert(String, Map<String, Object>) : void
When mongoDBClient.insert(collection, oneDocument)
When def countAfterInsertOne = mongoDBClient.count(collection)
Then karate.log('mongoDBClient.count(',collection,')=', countAfterInsertOne)
Then assert countAfterInsertOne == 1

Insert Many Documents in a collection

Inserts one or more documents in the collection.

Java Signature
public void insertMany(final String collectionName, final List<Map<String, Object>> values)
Gherkin Usage
# Define collection
Given def collection = "data"

# Define Data
Given def manyDocuments = [ { "_id": "2", "name": "karate-02", "value": 2 }, { "_id": "3", "name": "karate-03", "value": 3 } ]

When mongoDBClient.insertMany(collection, manyDocuments)
When def countAfterInsertMany = mongoDBClient.count(collection)
Then karate.log('mongoDBClient.count(',collection,')=', countAfterInsertMany)
Then assert countAfterInsertMany == 3

Replace a document in the collection