4

We use Drupal 7 as our base CMS tool.

For one specific product, something like an ERP, we've created sort of a non-drupal layer, to keep our specific business code in.

It would be something like this:

-------------
|  Business | -> This would be our business specific code layer
-------------
|    Glue   | -> This is where we connect with the basic Drupal API as we need
-------------
|   Drupal  | -> This is Drupal API
-------------

We have the concept of Repository, which is a basic class that retrieves something from the database in the form of an Entity or a ArrayObject of Entities.

This layer is connected to Drupal, since it needs access to the db_query() method, from the Drupal 7 API.

Our whole Business layer is tested using PHPUnit, with 100% coverage.

Now we are trying to test the Glue layer as well, the unit of the Repositories, their return values and parameters.

In order to do that, we came to the conclusion that we would need to mock the Drupal database access API.

But to do that, what would be the correct or best approach?

  • Wrap the db_query function from Drupal into a class that could be mocked in the tests?
  • Not test the Repositories at all?
Pierre.Vriens
  • 233
  • 1
  • 2
  • 11
Daniel Ribeiro
  • 610
  • 6
  • 11
  • Do your Business layer unit tests involve using objects within the Glue layer, or are your tests for the Business layer completely separate? – CokoBWare Dec 21 '12 at 17:19
  • Exactly, our business layer is completed separated from the Glue layer, and we can test it without worrying about anything rather than the business layer itself. But the glue layer, as I mentioned, has its own objects, such as repositories. They are the ones we think we should be also testing. – Daniel Ribeiro Dec 21 '12 at 17:21
  • How orthogonal do you want Glue to be to the other layers? Do you intend to use Glue in other software systems as is, or is the coupling with the Drupal API important? – CokoBWare Dec 21 '12 at 17:41
  • That layer is just there for Drupal, nothing else. We have interfaces to define the layer's behaviour though, despite the platform we are working on. Say we change from Drupal to Magento, we would have to implement those interfaces on the Glue layer to connect to the Magento API just as we did for Drupal. That's why we are not sure to test those classes. – Daniel Ribeiro Dec 21 '12 at 17:45

2 Answers2

2

Well, as in many cases the answer to your question starts with... "It depends."

First, you should ask yourself "Is there any logic in the Repository / Glue layer?" I mean other than adapting to and from the D7 API. If the repositories for example have methods that offer a custom query language for you to find specific objects or set of objects, methods that do selecting and sorting these objects, than you probably wish to test the Repository.

The ideal way to do it would be as you suggested, with a Mock of an intermediary class to db_query(). But before you jump into this and start coding take a minute and think about your repositories. Maybe it is acceptable to test it with a real database specially prepared with objects you know and can control for testing purposes. I find that most of the time, these very rarely changing parts of your design can be tested at this higher level. The test will run a little bit slower, but maybe you can get away with running them together with the functional / integration tests you may have on your system. After all, the whole "glue" thing is for integration.

You may also speed up the tests with databases by creating the databases in RAM only, or on a mount point serving as ram-disk.

Patkos Csaba
  • 2,054
  • 12
  • 16
  • Thanks for the brilliant answer. Concerning the repository objects, they don't have any business specific code, but they do some specific stuff, such as transform drupal `nodes` into `entities`, and that process only is already worth testing, in my opinion. When it comes to test them with a real database, that kind of scares me a little bit. That's why I instantly thought of mocking the database class. It could be an option though, to work with memory, as you mentioned. The fact that we have functional tests, in my opinion, make this an unnecessary thing to do. – Daniel Ribeiro Dec 21 '12 at 17:42
  • Well, if you have enough confidence in your functional tests, than don't explicitly test the glue. – Patkos Csaba Dec 22 '12 at 17:09
0

Based on your additional comments, I personally would not bother mocking any class up to simulate the Drupal API. It sounds as if you've designed Glue to abstract the Drupal API a bit from the Business layer, to make it easier to work with.

To provide reasonable test coverage for Glue without going overboard, I might suggest doing some basic black-box unit tests against the Drupal API calls you intend to use to ensure they are working as expected. You'll have confidence that the Drupal API is doing what is expected, and that you're integrating against a working API. Then you should test Glue and the Drupal API together. Once you've defined your tests and you execute them to your satisfaction, I would consider Glue tested sufficiently.

Under this approach, since you're not intending to use Glue with any other API other than Drupal, I think you'll have tested Glue adequately without burning extra cycles creating more work for yourself than needed.

CokoBWare
  • 538
  • 2
  • 8