I'm still a pretty novice mocker :(

Discussion of testing theory and practice, including methodologies (such as TDD, BDD, DDD, Agile, XP) and software - anything to do with testing goes here. (Formerly "The Testing Side of Development")

Moderator: General Moderators

Post Reply
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

I'm still a pretty novice mocker :(

Post by Luke »

Even though I've been using TDD for over a year at least, I still am a very poor mocker. I just can't seem to get the hang of mocking. So, I think what would help me is if I provide an example of a real world problem I have run into, and get some help doing mocks for it. So here goes...

I have an abstract class qCal_Value_Multi, and I want to test that it can contain multiple values. I do not want to have to create an actual child class just to test it. I'd like to be able to test its base functionality before getting more specific with child classes. So how would I go about this?

I already have qCal_Value, and it is well-tested. qCal_Value_Multi is an abstract class that extends qCal_Value (another abstract). Here is my (bare-bones) unit test case:

Code: Select all

<?php
/**
 * This is a series of tests that ensure that data is property handled in the qCal_Value family of classes
 */
class UnitTestCase_Value extends UnitTestCase {
 
   
    /**
     * Any "multi-value" values should be capable of containing multiple values, separated by commas
     */
    public function testMultiValuesContainListSeparatedByCommas() {
    
        
    
    }
 
}
It is pretty late, but still... I can't seem to figure out where to go here... I have been cheating and just implementing sub-classes and testing those instead of mocking. Somebody please shine some light on this for me :( Should I create an actual subclass of qCal_Value_Multi named MockqCal_Value_Multi and test that?
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Re: I'm still a pretty novice mocker :(

Post by Jenk »

I do not want to have to create an actual child class just to test it.
There lies your problem, creating a stub child class for "testing only" is not an invalid way to go. :)

Lets say your class was like this:

Code: Select all

abstract class qCal_Value {
  public function getCommaSeparatedList () {
    return implode($this->getDataArray(), ",");
  }
  abstract function getDataArray();
}
 
class ValueStub extends qCal_Value {
  public function getDataArray() {
    return array("a", "b", "c");
  }
}
Then the test would be:

Code: Select all

 
public function testMultiValuesContainListSeparatedByCommas() {
  $calVal = new ValueStub();
  $this->assertEqual($calVal->getCommaSeparatedList(), "a,b,c");
}
HTH :)
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Re: I'm still a pretty novice mocker :(

Post by Chris Corbyn »

I'm not sure what you're trying to achieve here. Before I begin, can I just make sure that you're not trying to test an abstract class by using a mock? I mean, the SUT itself is not the abstract class? Don't do this, just test each concrete implementation if this is the case. Mocks are used to stand in for dependencies, not to represent the SUT.

But assuming you're talking about something else, could you maybe post a use-case of the code you're looking to test? :)

EDIT | Or if you really want to test the abstract class use a test-specific subclass as Jenk says. Though this might not be very ideal for more complex abstract classes. The thing is, abstract classes usually arise as the result of refactoring and therefore the tests should probably already have been written for the concrete implementation(s).
jmut
Forum Regular
Posts: 945
Joined: Tue Jul 05, 2005 3:54 am
Location: Sofia, Bulgaria
Contact:

Re: I'm still a pretty novice mocker :(

Post by jmut »

From what I see the point is that you want to test getCommaSeparatedList so you stub the getDataArray() (which possibly involves db calls, intense call etc) and focus test on really if getCommaSeparatedList is doing correct work
josh
DevNet Master
Posts: 4872
Joined: Wed Feb 11, 2004 3:23 pm
Location: Palm beach, Florida

Re: I'm still a pretty novice mocker :(

Post by josh »

Instead of mocking I'd use stubbing. Indeed simpletest calls these mocks but I will refer to them as stubs. Basically I'd just keep doing what you're doing, but create the child class as a stub, by that I mean have empty methods. Wether you hard code return values as string constants or use $mockObj->setReturnValue() is entirely up to you. I use the "stub" framework so that when I do create the implementation for that class I don't have to worry about updating any constants in the tests.

In Jenk's example to stub it I'd just create a stub that implements getCommaSeperatedList() and its implementation would be return 'a, b, c'
Post Reply