du13932014807 2016-01-29 16:23
浏览 60
已采纳

绕过mysqli_connect()错误来编写单元测试

I'm trying to write a set of unit tests using PHPUnit (DISCALIMER: This is my first project attempting to use unit tests for improving code quality).

I'm currently have the a ConnectionManager class which is managing the connection to the MySQL databases. This class has two member functions: GetDBSetLinks and ConnectWithMysqli.

GetDBSetLinks is a function that takes in an array of connection information for multiple mysql databases (each element contains Hostname, Username, etc. and some other info), and passes this information into ConnectWithMysqli.

ConnectWithMySqli() calculates which overload of the mysqli_connect() function the program should use to connect the the MySQL database and then calls that overload using the passed in parameters.

When I pass bad connection information (such as a bad password) into GetDBSetLinks() using my unit test, the bad information is handled properly makes it to the ConnectWithMySqli function as expected. When the bad information hits mysqli_connect(), the function fails and triggers the expected

mysql_connect(): Access denied for user 'root'@'192.168.1.113' (using password:YES)" error.

The problem is that this also terminates execution of ConnectWithMySqli(), thus ConnectWithMysqli() will not complete and return the variable that I am trying to test against.

What I would like to do is to keep the program running but trigger an exception that can be handled.

Problem is I just started using try-catch and I'm not really sure the best way to do this. Anyone have any ideas?

Connection.php

<?php

class FailedConnection extends Exception{}

class ConnectionManager {
    //FUNCTION: Gets List of Database Links for given database set----------------//
    static public function GetDBSetLinks($CurrentDBSet){
        $DatabaseLinkList = array();

        foreach ($CurrentDBSet as $DatabaseInfoString){
            //Split the Database info string by commas. The input string found in the
            //configuration file is a single string containing all of the parameters
            //needed to connect to the SQL database. The statement below takes this string
            //and converts it into three separate variables, so that they can be passed into mysqli_connect()
            $SplitDBInfo = preg_split('/,/', $DatabaseInfoString);

            //Initialize a variable that serves as an iterator. This variable also holds
            //the number of arguments that were found in the config fie.
            $NumArgs = 0;

            //Initialize other variables necessary to connect to the current database.
            $DatabaseID = "NULL";
            $HostName = "NULL";
            $dbUsername = "NULL";
            $dbPassword = "NULL";
            $DatabaseName = "NULL"; //NOTE: Database name in the config file should exactly match the name of the database on the server.
            $PortNumber = "NULL";
            $Socket = "NULL";

            //Cycle through the individual params now stored in SplitDBInfo, (1.) count
            //them, then (2.) assign them to the appropriate variable to pass into mysqli_connect()
            foreach ($SplitDBInfo as $Parameter){
                $NumArgs ++; //(1.)              
                switch ($NumArgs) { //(2.)
                    case 1:
                        $DatabaseID = $Parameter;
                        break;
                    case 2:
                        $HostName = $Parameter;
                        break;
                    case 3:
                        $dbUsername = $Parameter;
                        break;
                    case 4:
                        $dbPassword = $Parameter;
                        break;
                    case 5:
                        $DatabaseName = $Parameter;
                        break;
                    case 6:
                        $PortNumber = $Parameter;
                        break;
                    case 7:
                        $Socket = $Parameter;
                        break;
                    default:
                        break;
                }
                //print $Parameter . "<br>"; //DEBUG
            }
            print '<br>' ."NumArgs: " . ($NumArgs) . '<br>'; //DEBUG ONLY
            print "Number of Function Arguments: " . ($NumArgs -1) . '<br>'; //DEBUG ONLY;
            echo "Connecting to Database '" . $DatabaseID . "' at hostname " . $HostName ."." . '<br>';

            $link = self::ConnectWithMysqli($NumArgs, $HostName, $dbUsername, $dbPassword, $DatabaseName, $PortNumber, $Socket);


            //If our link to the database is not successful, escape this sequence and do not put the link in our list of linked databases.
            if (!$link){
                echo "No Successful link to '" . $DatabaseID . "' at hostname " . $HostName .".";
                echo '<br>';
            }
            //Otherwise, our link should be good, and we should add it to our list of database links.
            else{
                echo "Connection to Database '" . $DatabaseID . "' at hostname " . $HostName ." was successful.";
                echo '<br>';
                array_push($DatabaseLinkList, $link);
            }    
        }
    //After we finish iterating to generate a list of viable links, we can use these
    //links to perform database operations.
    return $DatabaseLinkList;
    }

    function ConnectWithMysqli($NumArgs,$HostName, $dbUsername, $dbPassword, $DatabaseName, $PortNumber, $Socket){
        switch($NumArgs) {
            case 2:
                $link = mysqli_connect($HostName);
                //could not connect
                break;
            case 3:
                $link = mysqli_connect($HostName,$dbUsername);
                break;
            case 4:
                $link = mysql_connect($HostName,$dbUsername,$dbPassword);
                //$link = mysqli_connect($HostName,$dbUsername,$dbPassword);
                break;
            case 5:
                print ($DatabaseName);
                $link = mysqli_connect($HostName,$dbUsername,$dbPassword,$DatabaseName);
                break;
            case 6:
                $link =  mysqli_connect($HostName, $dbUsername, $dbPassword, $DatabaseName, $PortNumber, $Socket);
                break;
            default:
                throw new FailedConnection;
            }
    try{
        if(!$link){
            throw new FailedConnection;
        }
    }
    catch(FailedConnection $e){
        return "Null";
    }

return $link;
}  

ConnectionModuleTest.php

<?php
require_once 'C:\Users\bsnider\Documents\BrandonDepot\SourceControl\gitepos\GLS_DBSearchProject\Connection.php';

class ConnectionModuleTest extends PHPUnit_Framework_TestCase{
    public function setUp(){}
    public function tearDown(){}

    public function testDataGetDBSetLinks_GoodConnection(){
        $ConnectionManager = new ConnectionManager;
        //Valid Connection Parameters
        $DBSet = array('MainDatabase,192.168.1.41,root,colt45', 'MainDatabase,192.168.1.41,root,colt45');
        $Result = $ConnectionManager->GetDBSetLinks($DBSet); //$Result
        $this->assertNotEmpty($Result);
    }

    public function testDataGetDBSetLinks_BadHostName(){
        $ConnectionManager = new ConnectionManager;
        //Invalid Connection Parameters
        $DBSet = array('MainDatabase,192.168.1.20,root,colt45', 'MainDatabase,192.168.1.20,root,colt45');
        $Result = $ConnectionManager->GetDBSetLinks($DBSet); //$Result
        $this->assertEmpty($Result);
    }

    public function testDataGetDBSetLinks_BadPassword(){
        $ConnectionManager = new ConnectionManager;
        //Invalid Connection Parameters
        $DBSet = array('MainDatabase,192.168.1.41,root,badpassword', 'MainDatabase,192.168.1.41,root,badpassword');
        $Result = $ConnectionManager->GetDBSetLinks($DBSet); //$Result
        $this->assertEmpty($Result);        
        }
    public function testConnectWithMysqli(){

    }
}
  • 写回答

1条回答 默认 最新

  • dongqi3533 2016-01-29 16:55
    关注

    I think you should attempt to convert all possible errors into exceptions, so that you can use try/catch as you wish.

    The first library in this list can help you do that.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料