Testing type hinted parameters

Do people have an opinion on testing the type hinting of method parameters?

Assume I’ve a method which accepts a typehinted object


class example
{

      public function setSomeValue(SpecificObject $someValue)
      {
      }
}


The type hint enforces that someValue is an instance of SpecificObject or NULL so what should you unit test about acceptable inputs to setSomeValue?

  • Just how the method handles NULL and take the type hint as a given?
  • That other values fail, by trying them?
  • That other values fail, by using introspection to prove the type hint exists.

Whilst anyone reading the code can see the type hint I’m tempted to add some sort of test for it because the long term values of the tests is to record the intended behavior of the class. Am I being nuts?

If i am not wrong this is related to the white box testing

you can try this: http://php.net/manual/en/language.oop5.typehinting.php
search for class Typehint

It looks like you’ve decided to add a hint and only later decided to test it. However I think the best way to write code is test-first. First you describe a little piece of behaviour in a test and then write the minimum of code to make it pass.

As a rule, hints don’t actually do anything useful. They don’t add any functionality. Essentially they are just comments, some meta-information about the code. If you’re guided by the principle of always doing the simplest thing, hints often can’t seem to justify their existence.

There are exceptions. If you’re doing anything introspective you might need that meta-information. For example, a dependency injection container like Phemto can use typehints as a guide to fill dependencies. Although hints can add a lot of pointless verbosity I wouldn’t say they’re completely useless.

As an example of a test involving type hints, here’s one from Phemto which checks that objects are created OK in an $injector->create(…) call.


interface Hinted { }

class NeededForConstructor { }

class HintedConstructor implements Hinted {
    function __construct(NeededForConstructor $one) {
        $this->one = $one;
    }
}

class HintedConstructorWithDependencyChoice implements Hinted {
    function __construct(InterfaceWithManyImplementations $alternate) {
        $this->alternate = $alternate;
    }
}

class RepeatedHintConstructor {
    function __construct(NeededForConstructor $first, NeededForConstructor $second) {
        $this->args = array($first, $second);
    }
}

class CanAutomaticallyInjectTypeHintedDependencies extends UnitTestCase {
    function testSimpleDependenciesAreFulfilledAutomatically() {
        $injector = new Phemto();
        $this->assertIdentical($injector->create('HintedConstructor'),
                               new HintedConstructor(new NeededForConstructor()));
    }

    function testRepeatedHintJustGetsTwoSeparateInstances() {
        $injector = new Phemto();
        $injector->willUse('SecondImplementation');
        $this->assertEqual(
                $injector->create('RepeatedHintConstructor'),
                new RepeatedHintConstructor(new NeededForConstructor(), new NeededForConstructor()));
    }
}

Here the test specifies a fundamental, domain requirement: ie the container can instantiate objects with type-hinted dependencies. It’s testing Phemto’s introspective abilities. I don’t think you’d ever want to test a hint by bombarding a class with a series of good and bad dependency candidates. That’s getting too bogged down in details - and the best way to avoid that is always write the test first before writing any code.

Most of the time there is no need for introspection and type hints will not relate to any kind of real requirement. Therefore they don’t have to be tested or added to the code.

Simply put: you don’t. You’re testing the unit that you’re testing, not PHP’s ability to check type hints. If you want to test the communication between the object you’re testing and the object that’s mentioned in the type hint, then use a Mock object.

Don’t test your language, test your high level logic.
Don’t test that getters and setters simply work, check the confusing stuff, like your black/whitelisting (ex “A category should be shown if no whitelist is in effect” would be a spec the user cares about, so write a test for that). If the user does not care, don’t test it.