Repository: kaizendorks/pymongo_inmemory

Issue:
The client loses database name
**Describe the bug**
**To Reproduce**
```
>>> import pymongo_inmemory
>>> client = pymongo_inmemory.MongoClient("mongodb://127.0.0.1/test")
{"t":{"$date":"2023-09-28T10:08:22.707Z"},"s":"I",  "c":"CONTROL",  "id":5324701, "ctx":"-","msg":"Test storage engine does not support enableMajorityReadConcern=true, forcibly setting to false","attr":{"storageEngine":"ephemeralForTest"}}
{"t":{"$date":"2023-09-28T10:08:22.709Z"},"s":"W",  "c":"CONTROL",  "id":4788401, "ctx":"-","msg":"Lock-free reads is not compatible with enableMajorityReadConcern=false: disabling lock-free reads."}
>>> client._MongoClient__default_database_name
>>> client.get_default_database()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File ".../site-packages/pymongo/mongo_client.py", line 2247, in get_default_database
    raise ConfigurationError("No default database name defined or provided.")
pymongo.errors.ConfigurationError: No default database name defined or provided.
>>>
```
**Expected behavior**
The database name from the connection strings should be kept.

**Logs**
```
class MongoClient(pymongo.MongoClient):
    def __init__(self, host=None, port=None, **kwargs):
        self._pim_context: Context = Context()
        self._mongod = Mongod(self._pim_context)
        self._mongod.start()
        super().__init__(self._mongod.connection_string, **kwargs)
```
Probably this happens because the `host` argument is not sent to `pymongo.MongoClient`'s constructor.

**Screenshots**


**Context:**
 - MacOS
 - pymongo_inmemory==0.3.1


Discussion:

Patch:
diff --git a/README.md b/README.md
index 0411738..1819c0e 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,7 @@ A mongo mocking library with an ephemeral MongoDB running in memory.
 
 - Tooling enhancements. [[PR #90](https://github.com/kaizendorks/pymongo_inmemory/pull/90)]
 - Configuration for data directory. [[PR #90](https://github.com/kaizendorks/pymongo_inmemory/pull/91)]
+- Configuration for data directory. [[PR #90](https://github.com/kaizendorks/pymongo_inmemory/pull/94)]
 
 ### v0.3.1
 
@@ -74,6 +75,8 @@ with MongoClient() as client:
 |         | `download_folder`    | Override the default download location.                                                                    | pymongo_inmemory/.cache/download                                                                                           |
 |         | `extract_folder`     | Override the default extraction location.                                                                  | pymongo_inmemory/.cache/extract                                                                                            |
 | **NEW** | `mongod_data_folder` | Provide a data folder to be used by MongoD.                                                                | A `TemporaryDirectory` will be used                                                                                        |
+| **NEW** | `mongo_client_host`  | Hostname or connection string                                                                              |                                                                                                                            |
+| **NEW** | `dbname`             | Provide a database name to connect                                                                         | 'pimtest'                                                                                                                  |
 |         |                      |                                                                                                            |
 
 - \***_Note 1:_** Generic Linux version offering for MongoDB ends with version **4.0.23**. If the operating system is just `linux` and if selected MongoDB version is higher, it will default to `4.0.23`.
diff --git a/pymongo_inmemory/_pim.py b/pymongo_inmemory/_pim.py
index 5c924c0..072938a 100644
--- a/pymongo_inmemory/_pim.py
+++ b/pymongo_inmemory/_pim.py
@@ -7,6 +7,10 @@ from .context import Context
 class MongoClient(pymongo.MongoClient):
     def __init__(self, host=None, port=None, **kwargs):
         self._pim_context: Context = Context()
+        if port is not None:
+            self._pim_context.mongod_port = port
+        if host is not None:
+            self._pim_context.mongo_client_host = host
         self._mongod = Mongod(self._pim_context)
         self._mongod.start()
         super().__init__(self._mongod.connection_string, **kwargs)
diff --git a/pymongo_inmemory/context.py b/pymongo_inmemory/context.py
index e52083c..a1c0639 100644
--- a/pymongo_inmemory/context.py
+++ b/pymongo_inmemory/context.py
@@ -104,6 +104,8 @@ class Context:
         self.mongo_version = conf("mongo_version", version)
         self.mongod_port = conf("mongod_port", None, coerce_with=int)
         self.mongod_data_folder = conf("mongod_data_folder", None)
+        self.dbname = conf("dbname", "pimtest")
+        self.mongo_client_host = conf("mongo_client_host", None)
 
         self.operating_system = self._build_operating_system_info(os_name)
         self.os_version = conf("os_version", os_ver)
@@ -131,10 +133,11 @@ class Context:
             f"Mongo Version {self.mongo_version}\n"
             f"MongoD Port {self.mongod_port}\n"
             f"MongoD Data Folder {self.mongod_data_folder}\n"
+            f"Database Name {self.dbname}\n"
             f"OS Name {self.operating_system}\n"
             f"OS Version {self.os_version}\n"
             f"Download URL {self.download_url}\n"
-            f"URL hash {self.url_hash}\n"
+            f"URL Hash {self.url_hash}\n"
             f"Download Version {self.downloaded_version}\n"
             f"Ignore Cache {self.ignore_cache}\n"
             f"Use Local MongoD {self.use_local_mongod}\n"
diff --git a/pymongo_inmemory/mongod.py b/pymongo_inmemory/mongod.py
index 6b0fc58..dc9a00b 100644
--- a/pymongo_inmemory/mongod.py
+++ b/pymongo_inmemory/mongod.py
@@ -61,6 +61,26 @@ class MongodConfig:
         else:
             return set_port
 
+    @property
+    def connection_string(self):
+        if self._pim_context.mongo_client_host is not None:
+            if self._pim_context.mongo_client_host.startswith("mongodb://"):
+                return self._pim_context.mongo_client_host
+            else:
+                self.local_address = self._pim_context.mongo_client_host
+
+        if self.local_address is not None and self.port is not None:
+            if self._pim_context.dbname is None:
+                return "mongodb://{host}:{port}".format(
+                    host=self.local_address, port=self.port
+                )
+            else:
+                return "mongodb://{host}:{port}/{dbname}".format(
+                    host=self.local_address,
+                    port=self.port,
+                    dbname=self._pim_context.dbname,
+                )
+
 
 class Mongod:
     """Wrapper for MongoDB daemon instance. Can be used with context managers.
@@ -146,12 +166,11 @@ class Mongod:
         if self._connection_string is not None:
             return self._connection_string
 
-        if self.config.local_address is not None and self.config.port is not None:
-            self._connection_string = "mongodb://{host}:{port}".format(
-                host=self.config.local_address, port=self.config.port
-            )
-        else:
-            self._connection_string = None
+        self._connection_string = (
+            self.config.connection_string
+            if self.config.connection_string is not None
+            else None
+        )
 
         return self._connection_string
 


Test patch:
diff --git a/tests/unit/test_mongod.py b/tests/unit/test_mongod.py
index 986c7be..8f4f9a9 100644
--- a/tests/unit/test_mongod.py
+++ b/tests/unit/test_mongod.py
@@ -2,7 +2,6 @@ import subprocess
 
 from pymongo_inmemory.mongod import Mongod
 import pymongo_inmemory.downloader as downloader
-from pymongo_inmemory.context import Context
 
 
 class Popen:
@@ -25,13 +24,33 @@ def download():
     return ""
 
 
-def test_mongod(monkeypatch):
+def test_mongod_data_folder_config(monkeypatch):
     monkeypatch.setattr(subprocess, "Popen", Popen)
     monkeypatch.setattr(Mongod, "is_healthy", returns_true)
     monkeypatch.setattr(downloader, "download", download)
 
-    context = Context()
-    context.mongod_data_folder = "TEST"
+    monkeypatch.setenv("PYMONGOIM__MONGOD_DATA_FOLDER", "TEST")
 
-    with Mongod(context) as md:
+    with Mongod(None) as md:
         assert md.data_folder == "TEST"
+
+
+def test_dbname_config(monkeypatch):
+    monkeypatch.setattr(subprocess, "Popen", Popen)
+    monkeypatch.setattr(Mongod, "is_healthy", returns_true)
+    monkeypatch.setattr(downloader, "download", download)
+
+    monkeypatch.setenv("PYMONGOIM__DBNAME", "TEST")
+
+    with Mongod(None) as md:
+        assert md.config.connection_string.endswith("TEST")
+
+
+def test_mongo_client_host_config(monkeypatch):
+    monkeypatch.setattr(subprocess, "Popen", Popen)
+    monkeypatch.setattr(Mongod, "is_healthy", returns_true)
+    monkeypatch.setattr(downloader, "download", download)
+    monkeypatch.setenv("PYMONGOIM__MONGO_CLIENT_HOST", "mongodb://test")
+
+    with Mongod(None) as md:
+        assert md.config.connection_string == "mongodb://test"