doudi4137 2011-03-12 08:10
浏览 49
已采纳

在PHP中使用模拟对象,在实例化自己的对象的函数中

I have been looking into how to add unit testing coverage to a large, existing codebase written in PHP. Many functions in both static and instantiable classes make a call to a library or instantiate an object in order to obtain connections to memcache and the database. They typically look something like this:

public function getSomeData() {
    $key = "SomeMemcacheKey";
    $cache = get_memcache();

    $results = $cache->get($key);
    if (!$results) {
        $database = new DatabaseObject();
        $sql = "SELECT * from someDatabase.someTable";
        $results = $database->query($sql);

        $cache->set($key, $results);
    }

    return $results;
}

My colleagues and I are currently trying to implement coverage via PHPUnit for a few of the new classes we are writing. I have attempted to find a way to create unit tests in an isolated manner for functions in our existing codebase that resemble the pseudo-code above, but have been unsuccessful.

The examples I've seen in the PHPUnit documentation all rely on having some method in the class by which a mock object can be attached to it, such as: $objectBeingTested->attach($mockObject); I looked at SimpleUnit, and saw the same thing there, the mock objects were being passed into the class via its constructor. This doesn't leave much room for functions which instantiate their own database objects.

Is there any way to mock out these sorts of calls? Is there another unit testing framework we can use? Or are we going to have to change the patterns we are using in the future in order to facilitate unit testing?

What I'd like to do is be able to swap out an entire class with a mock class when running tests. For instance, the DatabaseObject class could be replaced with a mock class, and any time it's instantiated during a test, it would actually be an instance of the mock version.

There has been talk in my team of refactoring our methods of accessing the database and memcache in new code, perhaps using singletons. I suppose that could help if we were to write the singleton in such a way that its own instance of itself could be replaced with a mock object...

This is my first foray into unit testing. If I'm doing it wrong, please say so. :)

Thanks.

  • 写回答

4条回答 默认 最新

  • doushe8577 2011-03-12 21:49
    关注

    In a perfect world, you'd have the time to refactor all your legacy code to use dependency injection or something similar. But in the real world, you often have to deal the hand you've been dealt.

    Sebastian Bergmann, the author of PHPUnit, wrote a test helpers extension that allows you to override the new operator with a callback and rename functions. These will allow you to monkey patch your code during testing until you can refactor it to be more testable. Granted, the more tests you write using this, the more work you'll have undoing it.

    Note: the Test-Helper extension is superseded by https://github.com/krakjoe/uopz

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 HFSS 中的 H 场图与 MATLAB 中绘制的 B1 场 部分对应不上
  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?