本文介绍了单元测试和静态方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

阅读并了解单元测试,试图理解以下文章解释了静态函数调用的困难.

Reading up and picking up on unit testing, trying to make sense of the following post on that explains the hardships of static function calls.

我不清楚这个问题.我一直认为静态函数是在类中汇总实用程序函数的一种不错的方法.例如,我经常使用静态函数调用进行初始化,即:

I don't clearly understand this issue. I have always assumed static functions were a nice way of rounding up utility functions in a class. For example, I often use static functions calls to initialise, ie:

Init::loadConfig('settings.php');
Init::setErrorHandler(APP_MODE);
Init::loggingMode(APP_MODE);

// start loading app related objects ..
$app = new App();

//阅读这篇文章后,我现在的目标是……

// After reading the post, I now aim for this instead ...

$init = new Init();
$init->loadConfig('settings.php');
$init->loggingMode(APP_MODE);
 // etc ...

但是,我为此类编写的几十个测试是相同的.我什么都没改变,他们仍然都过去了.我在做错什么吗?

But, the few dozen tests I had written for this class are the same. I changed nothing and they still all pass. Am I doing something wrong?

帖子的作者指出以下内容:

The author of the post states the following:

现在,我从帖子中了解到静态方法会创建依赖关系,但无法直观地理解为什么不能像常规方法那样轻松地测试静态方法的返回值?

Now, I understand from the post that static methods create dependencies, but don't grasp intuitively why one cannot test the return value of a static method just as easily as a regular method?

我将避免使用静态方法,但如果有的话,我很想知道何时使用静态方法.从这篇文章看来,静态方法几乎和全局变量一样邪恶,应该尽量避免.

I will be avoiding static methods, but I would of liked having an idea of WHEN static methods are useful, if at all. It seems from this post static methods are just about as evil as global variables and should be avoided as much as possible.

有关该主题的任何其他信息或链接,将不胜感激.

Any additional information or links on the subject would be greatly appreciated.

推荐答案

静态方法本身并不比实例方法难测试.当某个方法(静态方法或其他方法)调用 other 静态方法时会出现问题,因为您无法隔离正在测试的方法.这是一个很难测试的典型示例方法:

Static methods themselves aren't harder to test than instance methods. The trouble arises when a method--static or otherwise--calls other static methods because you cannot isolate the method being tested. Here is a typical example method that can be difficult to test:

public function findUser($id) {
    Assert::validIdentifier($id);
    Log::debug("Looking for user $id");  // writes to a file
    Database::connect();                 // needs user, password, database info and a database
    return Database::query(...);         // needs a user table with data
}

您想用此方法测试什么?

What might you want to test with this method?

  • 传递除正整数以外的任何值都会抛出InvalidIdentifierException.
  • Database::query()收到正确的标识符.
  • 找到匹配的用户后,返回null.
  • Passing anything other than a positive integer throws InvalidIdentifierException.
  • Database::query() receives the correct identifier.
  • A matching User is returned when found, null when not.

这些要求很简单,但是您还必须设置日志记录,连接到数据库,将数据加载到数据库等.Database类应独自负责测试其是否可以连接和查询. Log类应该对日志记录执行相同的操作. findUser()不必处理任何这些问题,但必须这样做,因为它取决于它们.

These requirements are simple, but you must also setup logging, connect to a database, load it with data, etc. The Database class should be solely responsible for testing that it can connect and query. The Log class should do the same for logging. findUser() should not have to deal with any of this, but it must because it depends on them.

如果相反,上述方法调用了DatabaseLog实例上的实例方法,则该测试可以传入具有特定于测试的脚本返回值的模拟对象.

If instead the method above made calls to instance methods on Database and Log instances, the test could pass in mock objects with scripted return values specific to the test at hand.

function testFindUserReturnsNullWhenNotFound() {
    $log = $this->getMock('Log');  // ignore all logging calls
    $database = $this->getMock('Database', array('connect', 'query');
    $database->expects($this->once())->method('connect');
    $database->expects($this->once())->method('query')
             ->with('<query string>', 5)
             ->will($this->returnValue(null));
    $dao = new UserDao($log, $database);
    self::assertNull($dao->findUser(5));
}

如果findUser()忽略调用connect(),为$id(上面的5)传递了错误的值或返回了null以外的任何其他内容,则上述测试将失败.优点是不涉及任何数据库,从而使测试快速而稳健,这意味着它不会因与测试无关的原因而失败,例如网络故障或错误的样本数据.它使您可以专注于真正重要的事情:findUser()中包含的功能.

The above test will fail if findUser() neglects to call connect(), passes the wrong value for $id (5 above), or returns anything other than null. The beauty is that no database is involved, making the test quick and robust, meaning it won't fail for reasons unrelated to the test like network failure or bad sample data. It allows you to focus on what really matters: the functionality contained within findUser().

这篇关于单元测试和静态方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-03 20:13
查看更多