Unit testing with Live Databases and/or How do I use Mock Objects?

November 30th, 2010 by rvdavid Leave a reply »

This is another live coding note. I’ve found my rhythm with TDD and currently bashing away at some unit tests for the Models and Service layers for a project I’m working on.

In tonights post, I’m going to write about how I get around with Unit Testing live databases.

Unit Testing with Live Databases

For my unit tests, I’m currently working with a live test database since I don’t fully understand the “power” of mock objects. If you have any links out there that’s worth noting, please be a friend and “link me”. I’m not going to pretend that I know everything and anything about Web Development. I know a lot, but the one thing that I do know is that I don’t know everything.

Mock Objects. WTF are you?

One thing which is mostly a mystery to me is the concept and practical application of Mock Objects in Unit testing. I’ve read several articles on Mock objects, but some of them delve into how to create Mock Objects rather than practical usage for mock objects in a live development setting. What problem exactly are mock objects trying to solve?

I get that it replaces other objects that the current class your testing will collaborate with, but I’m guessing that this is due to not having a setup like I currently have where I have the extra application code which easily gives me access to the db resource so that I can just as easily do this within my unit test as it would with mock objects… maybe? I’m confused.

How I use a live relational database in my unit test.

Anyway with that aside, I’ll continue on with this note on how I handle Unit testing with a Live Relational Test MySQL Database. I am currently unit testing a Members model. A member record can only exist if there is a Customer record. So you can imagine my Unit Test at this stage is pretty hairy.

As I said earlier, I use the live database in my Unit Tests. So I have a convenience method in my Bootstrapped Test Case (ControllerTestCase) called “runSQL”.

public function runSQL($SQL)
{
return $this->application
->getBootstrap()
->getResource(‘db’)
->query($SQL);
}

So the solution I’ve been running with is disabling foreign key checks in my setup() method for tests. That is. Run a raw SQL call of “SET FOREIGN_KEY_CHECKS = 0″ through the application’s db resource – for example:

protected function setUp()
{
parent::setUp();
$this->object = new Members_Model_Mapper_Members();
$this->runSQL(“SET FOREIGN_KEY_CHECKS = 0″);
}
}
I truncate the database on tear down anyway so it’s of no real consequence. I’m not testing if the database handles foreign key checks, I’m testing CRUD methods mostly.
protected function tearDown()
{
$this->runSQL(“TRUNCATE `promotions_members`”);
}

I think disabling the foreign key checks takes some of the extra requirements of creating parent records in other tables unrelated to the unit tests I’m working with.

So far, I’ve not run into any hitches with this decision, but I may have overlooked something. So I’m throwing this idea out there.Can anyone out there see any issues with me doing this? Should I be using mock objects instead? If so, how would I apply mock objects to the scenario above?

Always happy with any feedback, otherwise, I hope this makes as much sense to someone else as it does for me at this point in time.

Till next time ;)

if you enjoyed this post, make sure you subscribe to my RSS feed!
You can also follow me on Twitter here.

Related posts:

  1. Unit Testing & TDD Keeps you focussed and gives you Peace of mind
  2. To copy and paste or not to copy and paste; adventures in unit testing
Advertisement

9 comments

  1. Here’s something I wrote a while back about mocks and testing DB code: http://codeutopia.net/blog/2009/06/26/unit-testing-4-mock-objects-and-testing-code-which-uses-the-database/

    There are some cases where you might want to use a real database while testing, though, such as functional or integration testing. In one project we used Selenium to test the user interaction flows through the application, in which case we obviously needed to have the entire application with the database and all running :)

  2. These posts may interest you:

    http://blueparabola.com/blog/getting-started-zendtest

    http://matthewturland.com/2010/01/04/database-testing-with-phpunit-and-mysql/

    Also, for practical examples, I use mock objects extensively in the unit test for Phergie. See the Phergie_TestCase and Phergie_Plugin_TestCase classes here: https://github.com/elazar/phergie/tree/master/Tests/Phergie

    Hope these resources help. :)

    • rvdavid says:

      Thank you Matthew, I’ll add these to my to-read list and I am looking forward to checking out your real project examples in Phergie.

      I am very grateful.

  3. marsbomber says:

    My understanding on mocking objects is that, when we do unit testing, we are only testing a single unit. dependencies required by the unit that’s under test should not effect the test results. To achieve this, we mock dependencies, and outline their expected behaviour.

    When testing comes down to the database level, theoretically, if DAOs are well abstracted, we could test our service layer classes without even need to have a testing database / testing dataset. But look, we all use data fixtures :)

    • rvdavid says:

      Thanks Jim, we have a relatively similar understanding of Mock Objects. What gets me is the whole If DAOs are well abstracted we could test dependent classes etc and code in expected results.

      What’s got me in analysis paralysis mode is that I don’t get the practical application of it.

      I’m _definitely_ missing the point somewhere.

      Will be using Jani and Matthew’s recommended resources as learning material as soon as I get the chance. :)

  4. Intelisystem says:

    Hi,
    i found your blog through googling. your blog gives very good knowledge about how we can do testing of live database. how do i use live data base in our project.
    this blog are very important for web developer and wed design.

    Thank you,

  5. baltech says:

    Thanks for the given information…..:)

Leave a Reply

Notify me of followup comments via e-mail. You can also subscribe without commenting.