我正在使用遵循MVC模式的框架编写Facebook应用程序 - Kohna 3.2。我想测试我的服务器端代码。我决定为模型编写单元测试,并检查控制器/视图的功能测试。决定使用PHPUnit。
所以我很快就遇到了问题。如何在请求处理期间为使用外部api的控制器编写功能测试?
我不想使用真正的api调用。它们的执行需要很长时间,并且需要会话中的身份验证令牌,它很快就会到期此外,测试“在墙上写帖子”等内容会产生大量垃圾邮件。
我真的不知道如何嘲笑这个。当然我可以为外部api包装器库创建一个模拟对象,但我认为应该通过创建请求并检查其响应来进行功能测试。所以我没有看到一个可以注入模拟对象的地方..
你会怎么做?
答案 0 :(得分:2)
1)当测试使用API包装器的东西时,你应该模拟整个API包装器类并模拟抛出异常作为错误状态和测试,应用程序本身将如何对这些做出反应异常。
它可能应该停止执行某些操作,这些操作依赖于API响应,它应该显示一些用户友好的错误。
更重要的是,您可以(并且可能应该)测试API包装器上的哪些方法被调用+多少次以及传递了哪些参数。
<?php
public function testShowUser() {
$fb = $this->getMock( 'Facebook\Api' );
$fb->expects( $this->once() ) // if your library will call getUserInfo() more than once or never, the test will fail
->method( 'getUserInfo' )
->with( $this->equalTo( 'johndoe' ) ) // if the method will be called with different parameter, the test will fail
->will( $this->throwException( 'Facebook\NonExistingUser' ) );
$myApp = new MyApp( $fb );
$myApp->renderUser( 'johndoe' ); // if this will throw uncaught exception, the test will fail
$this->assertEquals(
array( 'The user you requested does not exist' ),
$myApp->getFlashMessages()
);
}
2)在测试 API包装器本身时,您可以模拟来自API的原始响应。
您应该将围绕HTTP通信的所有内容分离到某个特定的类(Curl包装器/具有自己的单元测试/),并假设服务器返回了一些特定的HTTP代码和响应。
您可以在文件中保存所有可能类型的响应,因此您可以将它们作为响应加载到测试中。
我建议这样做:
<?php
/**
* @expectedException Facebook\NonExistingUser
*/
public function testUnavailableApi() {
$curl = $this->getMock( 'CurlWrapper' );
$curl->expects( $this->once() )
->method( 'getBody' )
->will( $this->returnValue( file_get_contents( 'fb_404_response.json' ) ) );
$curl->expects( $this->once() )
->method( 'getStatusCode' )
->will( $this->returnValue( 404 ) );
$api = new Facebook\Api( $curl );
$api->getUserInfo( 'johndoe' );
}
答案 1 :(得分:0)
在回顾我自己未回答的问题时,我可以回答自己使用DIC(依赖注入容器)就是答案。它允许为测试环境提供不同的配置,或者在测试期间使用单个PHP进程时,甚至可以在执行测试之前设置模拟。