需要使用oracle存储过程测试功能

时间:2012-12-07 15:12:39

标签: zend-framework phpunit

我有这样的代码:

protected function _checkUserVisibility()
{
    try {
        if (!$params->getUsrParametr(self::ACTIVE_FIF)) { // calling oracle stored proc
            throw new Unitex_Exception('ALARM');
        }
    }
    catch (Exception $e) {
        $this->logOut();
        throw $e;
    }
}

这个函数来自另一个(等等)。

一个问题: 如何对代码部分进行单元测试?

EDIT1:

首先采取了呵呵http://framework.zend.com/manual/1.12/en/zend.test.phpunit.html 比得到的(希望) 测试过程是:

class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase {
..........
public function testLoginAction()
{
    $request = $this->getRequest();
    $request->setMethod('POST')
        ->setHeader('X_REQUESTED_WITH', 'XMLHttpRequest')
        ->setPost(array(
                'user'     => 'test_user',
                'password' => 'test_pwd',
        ));

        $filialId = 1;
        $stmt1 = Zend_Test_DbStatement::createUpdateStatement();
        $this->getAdapter()->appendStatementToStack($stmt1);
        $this->getAdapter()->appendStatementToStack($stmt1);
        $this->getAdapter()->appendStatementToStack($stmt1);
        $this->getAdapter()->appendStatementToStack($stmt1);

        $stmt1Rows = array(array('IRL_ALIAS' => 'RO_COMMON', 'ISADM' => 'N'));
        $stmt1 = Zend_Test_DbStatement::createSelectStatement($stmt1Rows);
        $this->getAdapter()->appendStatementToStack($stmt1);

        $this->dispatch('/user/login');// <-- crash here
    $this->assertController('user');
    $this->assertAction('login');
    $this->assertNotRedirect();
    $this->_getResponseJson();
}

2 个答案:

答案 0 :(得分:4)

在您的单元测试中,您绝不需要任何数据库交互。您的问题的答案是使用存根来实现数据库功能。

假设$ paramsSomeClass包含getUsrParametr的属性,例如从数据库获取内容。您正在测试_checkUserVisibility方法,因此您不关心SomeClass中发生的情况。你测试的方式看起来像这样:

class YourClass
{
    protected $params;

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

    public function doSomething()
    {
        $this->_checkUserVisibility();
    }

    protected function _checkUserVisibility()
    {
        try {
            if (!$this->params->getUsrParametr(self::ACTIVE_FIF)) { // calling oracle stored proc
                throw new Unitex_Exception('ALARM');
            }
        }
        catch (Exception $e) {
            $this->logOut();
            throw $e;
        }
    }
}

单元测试当然是你测试的唯一方法是公共方法,但你通过测试公共方法来覆盖受保护的方法。

public function testDoSomethingAlarm()
{
    // set expected exception:
    $this->setExpectedException('Unitex_Exception', 'ALARM');

    // create the stub
    $params = $this->getMock('SomeClass', array('getUsrParametr'));

    // and set desired result
    $params->expects($this->any())
        ->method('getUsrParametr')
        ->will($this->returnValue(false));

    $yourClass = new YourClass($params);
    $yourClass->doSomething();
}

如果getUsrParametr将返回true,那么测试用例的第二个测试:

public function testDoSomethingLogout()
{
    // set expected exception:
    $this->setExpectedException('SomeOtherException');

    // create the stub
    $params = $this->getMock('SomeClass', array('getUsrParametr'));

    // set throw desired exception to test logout
    $params->expects($this->any())
        ->method('getUsrParametr')
        ->will($this->throwException('SomeOtherException'));

    // now you want create mock instead of real object beacuse you want check if your class will call logout method:   
    $yourClass = $this->getMockBuilder('YourClass')
        ->setMethods(array('logOut'))
        ->setConstructorArgs(array($params))
        ->getMock();

    // now you want ensure that logOut will be called
    $yourClass->expects($this->once())
        ->method('logOut');

    // pay attention that you've mocked only logOut method, so doSomething is real one
    $yourClass->doSomething();
}

答案 1 :(得分:2)

如果你在PHPUnit中使用PHP 5.3.2+,你可以在运行测试之前使用反射将它们设置为公共来测试你的私有方法和受保护方法,否则你通过正确测试来测试受保护/私有方法使用protected / private方法的公共方法。一般来说,两个选项中的后一个通常是你应该怎么做,但如果你想使用反射,这是一个通用的例子:

protected static function getMethod($name) {
  $class = new ReflectionClass('MyClass');
  $method = $class->getMethod($name);
  $method->setAccessible(true);
  return $method;
}

public function testFoo() {
  $foo = self::getMethod('foo');
  $obj = new MyClass();
  $foo->invokeArgs($obj, array(...));
  ...
}