Test MongoDB Interactions in a PHP Application With Mocking

2.9k Views Asked by At

What is the best practice to work efficiently with MongoDB and PHPUnit? What should (or could) I use to mock objects that access MongoDB? PHPUnit Mocker, Mockery, Phrophecy, Phactory?

2

There are 2 best solutions below

1
Gates VP On BEST ANSWER

If you look at mocking data for SQL databases, there are lots of opinions here.

  • Some people suggest using an in-memory SQL database.
  • Some people just mock the ORM calls and assume that the ORM to DB portion is tested.
  • Some people just use a "local" DB for unit testing and just ignore the whole "mocking" concept.

Given the lack of consensus on SQL, it's even less likely that you will find consensus on the new DBs like MongoDB.

I think there are some important details to consider here.

  • Are you using some form of ORM / ODM? Just the driver directly?
  • Are you trying to mock all communications with the DB? Are you trying to mock the ODM?

If you are just trying to mock communications to DB, then the ideal solution is a "fake" implementation of the MongoDB driver. This is probably a lot of work as the driver was never written with "mockability" in mind.

If you have an ODM, then you can simply mock the ODM calls and assume the ODM is doing its job. Ideally the ODM should provide some mockable interface, but this is not always the case.

Again, this answer comes back down to what you're really planning to test and what you consider as a good unit test. Unfortunately, most of these products are still very new so there is very little guidance in this space.

2
Will On

Phactory provides direct support for mocking MongoDB.

Edit: Phactory is no longer maintained. However, I've found a new project called php-mongomock that seems to solve this problem:

<?php

use Helmich\MongoMock\MockCollection;

$collection = new MockCollection();
$collection->createIndex(['foo' => 1]);

$documentId = $collection->insertOne(['foo' => 'bar'])->insertedId();
$collection->updateOne(['_id' => $documentId], ['$set' => ['foo' => 'baz']]);