When Unit Testing and Frameworks Collide

I'm a big fan of unit testing. It allows me to be much more confident in the deployability of my code. And that's great. Without going into too much detail ( we can save that for another article ) a unit test is something that tests a small bit of code in isolation from the rest of the system. That small bit of code would, typically, be a class method.

So, what happens when that method relies on the database. Even that is really simple. With code that has been written with testability in mind, you create a mock object that "looks" to the system like the database. You then use that mock object to pretend to be the database and that is what the method is given instead of the real database.

We probably all know that we are talking about mocking and dependency injection and these are more things we should look at in other articles.

So, we have an idea of the utility of unit testing and why we should be a fan. We are also great fans of development frameworks. They save us from the mundane and make development so much faster, easier and for the really geeky amongst us, more fun.

But - what happens when they collide. Let me give you a real world indication of how this can happen using the Laravel/Lumen framework and PHPUnit.

Initially everything is fine. I mock my database models and inject them in my controllers and I can test without the database needing to even be running. That's my perfect world.

Now we use a framework feature. We add useSoftDeletes to a model. Suddenly everything goes wrong. PhpUnit can no longer mock that model. There is code in the framework that is not testable, possibly because of the use of singletons of static class members.

Stack overflow points us at a possible solution. We can introduce a factory to create a class just for testing. Unfortunately this isn't a mock object. It is a full scale database model that requires mysql.

And there is the collision.

Ease of framework against good test practice.

So what do we do? What's the important requirement here? We absolutely need to be able to soft delete, and we absolutely must be able to run a full suite of unit tests without reference to a real database.

I can either sacrifice a requirement or maybe find a different framework that doesn't suffer from this problem. Obviously sacrificing a requirement isn't going to fly. A requirement is... well, required!

If my project is fairly new then I can choose a different framework as I wouldn't have to redevelop too much, but even then I don't really want to. There must be a quicker way.

For me, the answer is simple. I can achieve both requirements by putting a little more effort into application development. Instead of just using the frameworks useSoftDeletes I can create my own soft delete code. I can even use some kind of intermediate class to make sharing those methods easier.

My version of the soft delete would then use testable code. I have sacrificed perhaps a few hours, and yes I have reinvented the wheel. But isn't that better than coupling a database to my unit tests?

I think so. That's what I'm doing. And that's how I'll resolve any further such clashes.

To view or add a comment, sign in

More articles by Paul Caligari

  • TDD for dummies like me

    TDD stands for Test Driven Development. With test driven development the test come first and the code is created to…

    1 Comment
  • Right and Wrong Ways to do development

    What’s the best way for developers to support the business? Building the best possible systems that adhere to the…

    2 Comments
  • Mocking APIs

    When we, as developers, write code we like to see it in action. To do that we execute it.

  • Constantly Id'ing problems...

    Time for another developer rant! I am constantly amazed by how foolish we developers can be. In this article I am going…

  • Do Design Patters Hold Hidden Dangers?

    Over the past 30 years I have seen a new language for developers to use emerge. It's the language of the design pattern.

  • Tracking Actions Through Multiple Micro Services

    In a monolithic application tracking what happens when a user clicks a button is relatively straightforward. You would…

    1 Comment
  • Programming from habit

    During an advanced driver training lesson, I was approaching a roundabout on an utterly empty dual carriageway, I could…

    2 Comments
  • Documenting Code

    I'm pretty sure we all hate documenting code, and we are all guilty of not updating the documentation when we make a…

  • Refactoring - why "fix" what isn't broken.

    First, what is refactoring? Refactoring is changing things, hopefully making them better. To use an example from…

  • Why use docblocks and type hinting.

    We all know from countless computer science lectures that commenting code is important. The reasons given are wide…

Explore content categories