PHP unit testing advanced (7) - core technology - stub (stub) - constructor injection stub

PHP unit testing advanced (7) - core technology - stub (stub) - constructor injection stub

The main code and text of this series of articles come from "The Art of Unit Testing", original author: Roy Osherove. Translator: Jin Ying.

This series of articles has been adapted according to the syntax and usage habits of php. All codes are tested locally. If reproduced, please indicate the source.
Source code (1) The interface IExtensionManager.php

extracted from t2\application\index\controller according to the test needs (actually decoupling, making the program clearer)

<?php
namespace app\index\controller;

/**
 * Whether the file name is valid interface
 * The file manager class in the source code will be implemented, and a stub will also be implemented
 * The existence of the interface makes the meaning of all codes clearer and more stable.
 */
interface  IExtensionManager
{
    /**
     * Determine if the file name is valid
     * @param string $filename
     * @return boolean
     */
    public function isValid($filename);
}

(2) The file manager class under t2\application\index\controller implements the above interface, but is actually excluded from the unit test, so it is not tested. Integration tests should be used to test this class.
FileExtensionManager.php
<?php
namespace app\index\controller;

/**
 * File manager class
 *
 */
class FileExtensionManager implements IExtensionManager
{
    /**
     * Determine whether the file name is valid based on the content of a configuration file
     * @param string $filename
     */
    public function isValid($filename)
    {
        // will use the file_get_contents function to read the contents of a file
        // This is not written here for brevity, because it is not the point.
        return true;
    }
}

(3) The class under test under t2\application\index\controller, the log analyzer. Constructor injection is used to write code, which is convenient for testing
LogAnalyzer.php
<?php
namespace app\index\controller;

/**
 * The log analyzer class is also the class under test
 *
 * Note that this is an example of injecting with a constructor.
 */
class LogAnalyzer
{
    /**
     * @var IExtensionManager
     */
    private $manager;

    public function __construct(IExtensionManager $mgr)
    {
        $this->manager = $mgr;
    }

    /**
     * To determine whether the file name is valid, call another class to implement
     * @param string $filename
     */
    public function isValidLogFileName($filename)
    {
        return $this->manager->isValid($filename);
    }
}

Test code

(4) Under t2\tests\index\controller\, the pile class is used to replace the file manager, which is convenient for testing
FakeExtensionManager.php
<?php
namespace tests\index\controller;
/**
 * A stub class for testing log analyzers, since log analyzers read files and hinder unit testing.
 */
class FakeExtensionManager implements \app\index\controller\IExtensionManager
{
    public $willBeValid = false;

    /**
     * Determine whether the file name is valid based on the content of a configuration file
     * @param string $filename
     */
    public function isValid($filename)
    {
        return $this->willBeValid;
    }
}


(5) Under t2\tests\index\controller\, the last is the test class, inject the stub LogAnalyzerTest.php with the construction method
<?php
namespace tests\index\controller;

/**
 * class for testing
 */
class LogAnalyzerTest extends \think\testing\TestCase
{

    /**
     * @test
     * Test using the method of injecting stubs from the constructor
     * Note that it is very important to make the test method names as meaningful as possible to facilitate the maintenance of the test code. regular
     */
    public function isValidFileName_NameSupportedExtension_ReturnTrue()
    {
        // prepare a stub that returns true
        $myFakeManager = new FakeExtensionManager();
        $myFakeManager->willBeValid = true;

        //Start creating the object of the class under test, ready to test
        $analyzer = new \app\index\controller\LogAnalyzer($myFakeManager);
        $result = $analyzer->isValidLogFileName("short.ext");
        $this->assertTrue($result);
    }
}

Open the cmd window and the test passes.

As an additional note, in this article, the source code is organized in the same namespace, and should not be placed under the controller namespace at least. This article is put together for brevity. Also, the test code doesn't matter, it's good

to it together stub - property injection stub

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327074769&siteId=291194637