努力理解单元测试

时间:2013-11-24 15:12:04

标签: php unit-testing phpunit

我刚刚开始使用我的项目进行单元测试,但我仍面临一个让我失望的问题。我真的很想知道单元测试,因为我知道长期的好处是值得学习的。

我几乎每天都在Twitter上广泛工作。我创建了许多与Twitter一起使用的应用程序。

在实际情况下,如果我想运行单元测试以测试登录是否成功(在这种情况下不使用API​​),我将如何在单元测试中测试这是否正确?我通常在生产代码中做的是测试是否在页面上设置了用户ID,或者是否存在只有登录用户才会拥有的某个cookie。然后失败,我抛出异常。

但是我如何在单元测试中测试它呢?

它与我在生产代码中的表现方式相同吗?例如,测试是否存在只有已登录用户的已知cookie?

有很多这样的场景,在考虑单元测试时我真的很难理解。

我知道在构建依赖第三方的应用程序时可能会有点棘手,因为第三方可能会改变它们的工作方式,并且在您更改之前测试是无用的。

2 个答案:

答案 0 :(得分:1)

在单元测试API或编写cookie时,您不能/不应测试cookie的存在或API已接受您的请求。

您知道正面API请求所需的格式和值。在测试API时,通常会对数据进行硬编码,以查看是否所有内容都能正常运行。如果是您的单元测试,请检查您通常发送给API的所需值是否具有API正常运行且没有错误的预期格式。您的单元测试不应该测试API本身。

与cookies相同。您只测试使用预期数据调用函数/方法,其中写入cookie时没有错误。您不会在单元测试中测试类似浏览器的内容。

答案 1 :(得分:1)

您在应用程序上手动执行的高级别测试(例如,手动登录然后检查某些cookie)可能不会被称为“单元测试”。单位测试,顾名思义,应测试应用程序的小组件。

请参阅this explanation of different types of test

当您使用外部服务时,常见的策略是创建其API的 Mocks 。它们允许您检查应用程序是否正在发出正确的请求并正确处理结果 - 而无需实际连接到API。

一个例子:

假设您的应用程序有一个类User。您可以为用户设置usernamepassword,然后将其告知login()到外部系统。您希望您的应用程序使用您设置的用户名和密码向该API发出请求。

这可以粗略地翻译成这样的PHPUnit测试:

public function testLogin() {
    // We create a mock of an existing wrapper class for the API
    $mockAPI = $this->getMock('ApiWrapperClass');

    // Create a new User instance, passing the mock API as a dependency
    $user = new User($mockApi);

    $user->username = "Test user";
    $user->password = "secret";

    // Now we set up the expectation of what should happen
    $mockApi->expects($this->once())
             ->method('login')
             ->with(
                 $this->equalTo("Test user"),
                 $this->equalTo("secret")
             )
             ->will($this->returnValue(TRUE));

    // Now we can call the actual function that we are testing
    $user->login();
}

模拟API只返回true以模拟成功登录。

PHPUnit文档有一个chapter on Mock objects