PHPUnit模拟类常量

时间:2014-08-08 02:08:46

标签: php oop mocking phpunit

我正在测试一个注入了依赖项的类。在我的无限聪明中,我在整个代码中分散了对依赖项类常量的引用。

(抱歉这个愚蠢的例子,想要偏离foobar。)

<?php

class Book_PhoneBook extends Book {

    private $author;

    public function __construct(Author $author) {
        $this->author = $author;
    }

    public function getCover() {
        return $this->author->getTitle(Author::NAME_UNKNOWN) . ' - YELLOW PAGES';
    }
}


class Author {
    const NAME_UNKNOWN = 'anonymous';

    public function getTitle($nameStyle) {
        //do complicated calculation of author name
        if ($nameStyle == $this::NAME_UNKNOWN) {
            $name = "Anonymous";
        }

        //do further complicated calculations, modifying $name

        return $name;
    }
}

我的问题是单元测试!当我模仿Author时,我得到“致命错误:未定义的类常量'NAME_UNKNOWN'”。模拟的整个目的是避免包含Author类文件,那么处理该常量的正确方法是什么?

我可以将Author分成几个对象,或者拆分依赖常量的方法,但这会引起很多重复。

2 个答案:

答案 0 :(得分:4)

您正在使用来自Author的类常量这一事实意味着您依赖于在您的代码中提供该类,因此也在您的测试中。因此,为了测试Book_PhoneBook,您需要使用常量Author类。如果类常量将是您需要传递给类的一系列标志,则需要使该类可用,并且在测试中确保已加载原始类。您依赖于Book_PhoneBook::getCover()的该课程。

你也可以在你的Book_PhoneBook中使用类常量的字符串值,尽管这样做会使它成为一个常量,这样你就可以在一个地方改变它。

通过您的示例,了解您要尝试实现的内容有点棘手,但由于您要删除AuthorBook_PhoneBook的依赖关系,我会将其更改为某些内容像这样:

<?php

class Book_PhoneBook extends Book {

    private $author;

    public function __construct(Author $author) {
        $this->author = $author;
    }

    public function getCover() {
        return $this->author->getTitle() . ' - YELLOW PAGES';
    }
}


class Author {
    const NAME_UNKNOWN = 'anonymous';

    public function __construct($nameStyle) {
       $this->nameStyle = $nameStyle;
    }

    public function getTitle() {
        //do complicated calculation of author name
        if ($this->nameStyle == $this::NAME_UNKNOWN) {
            $name = "Anonymous";
        }

        //do further complicated calculations, modifying $name

        return $name;
    }
}

此解决方案确实存在getTitle难以添加其他选项的问题。如果没有更好地了解您使用getTitle尝试实现的目标,我无法提供更好的解决方案。

答案 1 :(得分:2)

对于将来遇到这类问题的人,我最终根据@Schleis的答案结束了这个:

class Author {
    const NAME_UNKNOWN = 'anonymous';

    private function getTitle($nameStyle) {
        //do stuff, taking $nameStyle into account
        return $name;
    }

    public function getAnonymousTitle() {
        return $this->getTitle($this::NAME_UNKNOWN);
    }
}