How to Decouple Unit Tests
I'm trying to learn how to write unit tests the 'proper' way and only test a specific component. (Using http://blog.stevensanderson.com/2009/08/24/writing-great-unit-tests-best-and-worst-practises/ for reference) In one case, I've written a primative wrapper to query an old MS SQL 2000 database in PHP/PHPUnit. Without getting into specifics, it looks like this: $mssql = MSSQL::connect($credentials); $mssql->insert($table, $assoc_array_of_data); $mssql->select($table, $columns, $where_clauses); $mssql->update($table, $assoc_array_of_data, $where_clauses); $mssql->delete($table, $where_clauses); My question is, how would I structure a unit test to test each method in isolation, since they depend on each other? My current unit test basically does the following: // Connect to the DB // Insert a test row // Select it to verify it made it in // Update the test row // Select it to verify the update worked // Delete the test row // Select it and verify it isn't there Is this a proper approach to a unit test, or is there a better way?
This doesn't sound like code you'd want to unit test, since the purpose of it seems only to be interacting with a database. What you want here is integration testing which will verify that parts of your system work together correctly. CRUD tests like this are pretty common integration tests in my experience. It is possible that there is something worth unit testing here though. Does your code do anything besides forward requests to the database? I've seen some code like this that does things like formatting SQL commands from objects before sending them to the database engine. That's the kind of scenario where you could stub the database and verify that your query generation code is creating valid SQL queries. When figuring out how and what to unit test a lot of it comes down to whether or not you wrote the code. Ideally you'll be able to unit test all of the code you write yourself, but you'll usually get to some point where your code is just sending data or commands to 3rd party code, like a database. You'll want to minimize the amount of code that's strongly coupled to 3rd party code to make it more testable. How much of your example code depends on how much it does. If it's just a wrapper around existing 3rd party code there's not much for you to do. If it's doing anything else you can pull your code into external components and test those components in isolation.