Finishing up test case

Up to this point, you should have the follow pieces of files and code. class="figure" />

So what else can we test for at this point? A few reasonable tests are to see what happens if the project already exists, and what if the username does not exists.

First we shall refactor our test code since much of the setup code for the mocked connection will need to be repeated in other test assertions. We change the test case to have these three new methods.

function setupMockConnectionFor($project) { $customer = new TimeTrackerUser(); $customer->ID = 1; $customer->Name = "Customer A"; $manager = new TimeTrackerUser(); $manager->ID = 2; $manager->Name = "Manager A"; $conn = $this->connection; //return the customer and manager $conn->setReturnValue('queryForObject', $customer, array('GetUserByName', 'Customer A')); $conn->setReturnValue('queryForObject', $manager, array('GetUserByName', 'Manager A')); //project does not exist $conn->setReturnValue('queryForObject', null, array('GetProjectByName', 'Project 1')); $param['project'] = $project; $param['creator'] = $customer->ID; $param['manager'] = $manager->ID; $conn->setReturnValue('insert', true, array('CreateNewProject', $param)); $conn->setReturnReference('queryForObject', $project, array('GetProjectByID', 1)); } function createNewTestProject() { $project = new Project(); $project->Name = "Project 1"; $project->CreatorUserName = "Customer A"; $project->ManagerUserName = "Manager A"; return $project; } function assertProjectCreated($project) { $this->assertTrue($this->dao->createNewProject($project)); $this->assertEqual($this->dao->getProjectByID(1), $project); }

Our refactored test method testProjectDaoCanCreateNewProject() is as follows.

function testProjectDaoCanCreateNewProject() { $project = $this->createNewTestProject(); if(($conn = $this->connection) instanceof MockTSqlMapper) { $this->setupMockConnectionFor($project); $conn->expectMinimumCallCount('queryForObject', 3); $conn->expectAtLeastOnce('insert'); } $this->assertProjectCreated($project); }

To test that the project already exists, we modify the mock connection and test for an exception.

function testProjectExistsException() { $project = $this->createNewTestProject(); if(($conn = $this->connection) instanceof MockTSqlMapper) { //make the project exist $conn->setReturnValue('queryForObject', $project, array('GetProjectByName', 'Project 1')); $this->setupMockConnectionFor($project); } try { $this->assertProjectCreated($project); $this->fail(); } catch(TimeTrackerException $e) { $this->pass(); } }

Other test method for testing missing customer and manager users are done similarly. At this point, the test case file looks quite large. We shall not add more tests to this case and we should rename the file from ProjectDaoTestCase.php to CreateNewProjectTestCase.php.

Note: A heirachical exception class may be more useful in testing for specific exceptions. For simplicity, we decided to use only TimeTrackerException for this small project.
Tip:Class, method and file naming is very important to any project, the name should inform you at first glance what is to be expected from the class, method or file. In addition, the naming scheme should be uniform over the project.
Comment: These test may be too ridget as any changes to the implementation may actually cause the tests to fail. This is the case with grey-box/white-box testing, you are actually testing the implementation. Black box tests may be more preferable, as it should only test the class interface (the method or function details such as parameters and may be return values). However, with the use of database connection to retrive data within the objects under test, it may be more suitable to do intergration tests.