partial_mocks_documentation.html.svn-base
来自「PHP 知识管理系统(基于树结构的知识管理系统), 英文原版的PHP源码。」· SVN-BASE 代码 · 共 461 行 · 第 1/2 页
SVN-BASE
461 行
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Documentation SimpleTest : les objets fantaisie partiels</title><link rel="stylesheet" type="text/css" href="docs.css" title="Styles"></head><body><div class="menu_back"><div class="menu"><a href="index.html">SimpleTest</a> | <a href="overview.html">Overview</a> | <a href="unit_test_documentation.html">Unit tester</a> | <a href="group_test_documentation.html">Group tests</a> | <a href="mock_objects_documentation.html">Mock objects</a> | <a href="partial_mocks_documentation.html">Partial mocks</a> | <a href="reporter_documentation.html">Reporting</a> | <a href="expectation_documentation.html">Expectations</a> | <a href="web_tester_documentation.html">Web tester</a> | <a href="form_testing_documentation.html">Testing forms</a> | <a href="authentication_documentation.html">Authentication</a> | <a href="browser_documentation.html">Scriptable browser</a></div></div><h1>Documentation sur les objets fantaisie partiels</h1> This page... <ul><li> <a href="#injection">Le probl猫me de l'injection d'un objet fantaisie</a>. </li><li> D茅placer la cr茅ation vers une m茅thode <a href="#creation">fabrique prot茅g茅e</a>. </li><li> <a href="#partiel">L'objet fantaisie partiel</a> g茅n猫re une sous-classe. </li><li> Les objets fantaisie partiels <a href="#moins">testent moins qu'une classe</a>. </li></ul><div class="content"> <p> Un objet fantaisie partiel n'est ni plus ni moins qu'un mod猫le de conception pour soulager un probl猫me sp茅cifique du test avec des objets fantaisie, celui de placer des objets fantaisie dans des coins serr茅s. Il s'agit d'un outil assez limit茅 et peut-锚tre m锚me une id茅e pas si bonne que 莽a. Elle est incluse dans SimpleTest pour la simple raison que je l'ai trouv茅e utile 脿 plus d'une occasion et qu'elle m'a 茅pargn茅e pas mal de travail dans ces moments-l脿. </p> <p><a class="target" name="injection"><h2>Le probl猫me de l'injection dans un objet fantaisie</h2></a></p> <p> Quand un objet en utilise un autre il est tr猫s simple d'y faire circuler une version fantaisie d茅j脿 pr锚te avec ses attentes. Les choses deviennent un peu plus d茅licates si un objet en cr茅e un autre et que le cr茅ateur est celui que l'on souhaite tester. Cela revient 脿 dire que l'objet cr茅茅 devrait 锚tre une fantaisie, mais nous pouvons difficilement dire 脿 notre classe sous test de cr茅er un objet fantaisie plut么t qu'un "vrai" objet. La classe test茅e ne sait m锚me pas qu'elle travaille dans un environnement de test. </p> <p> Par exemple, supposons que nous sommes en train de construire un client telnet et qu'il a besoin de cr茅er une socket r茅seau pour envoyer ses messages. La m茅thode de connexion pourrait ressemble 脿 quelque chose comme...<pre><strong><?phprequire_once('socket.php');class Telnet { ... function &connect($ip, $port, $username, $password) { $socket = &new Socket($ip, $port); $socket->read( ... ); ... }}?></strong></pre> Nous voudrions vraiment avoir une version fantaisie de l'objet socket, que pouvons nous faire ? </p> <p> La premi猫re solution est de passer la socket en tant que param猫tre, ce qui force la cr茅ation au niveau inf茅rieur. Charger le client de cette t芒che est effectivement une bonne approche si c'est possible et devrait conduire 脿 un remaniement -- de la cr茅ation 脿 partir de l'action. En fait, c'est l脿 une des mani猫res avec lesquels tester en s'appuyant sur des objets fantaisie vous force 脿 coder des solutions plus resserr茅es sur leur objectif. Ils am茅liorent votre programmation. </p> <p> Voici ce que 莽a devrait 锚tre...<pre><?phprequire_once('socket.php');class Telnet { ... <strong>function &connect(&$socket, $username, $password) { $socket->read( ... ); ... }</strong>}?></pre> Sous-entendu, votre code de test est typique d'un cas de test avec un objet fantaisie.<pre>class TelnetTest extends UnitTestCase { ... function testConnection() {<strong> $socket = &new MockSocket($this); ... $telnet = &new Telnet(); $telnet->connect($socket, 'Me', 'Secret'); ...</strong> }}</pre> C'est assez 茅vident que vous ne pouvez descendre que d'un niveau. Vous ne voudriez pas que votre application de haut niveau cr茅e tous les fichiers de bas niveau, sockets et autres connexions 脿 la base de donn茅es dont elle aurait besoin. Elle ne conna卯trait pas les param猫tres du constructeur de toute fa莽on. </p> <p> La solution suivante est de passer l'objet cr茅茅 sous la forme d'un param猫tre optionnel...<pre><?phprequire_once('socket.php');class Telnet { ...<strong> function &connect($ip, $port, $username, $password, $socket = false) { if (!$socket) { $socket = &new Socket($ip, $port); } $socket->read( ... );</strong> ... return $socket; }}?></pre> Pour une solution rapide, c'est g茅n茅ralement suffisant. Ensuite le test est tr猫s similaire : comme si le param猫tre 茅tait transmis formellement...<pre>class TelnetTest extends UnitTestCase { ... function testConnection() {<strong> $socket = &new MockSocket($this); ... $telnet = &new Telnet(); $telnet->connect('127.0.0.1', 21, 'Me', 'Secret', &$socket); ...</strong> }}</pre> Le probl猫me de cette approche tient dans son manque de nettet茅. Il y a du code de test dans la classe principale et aussi des param猫tres transmis dans le sc茅nario de test qui ne sont jamais utilis茅s. Il s'agit l脿 d'une approche rapide et sale, mais qui ne reste pas moins efficace dans la plupart des situations. </p> <p> Une autre solution encore est de laisser un objet fabrique s'occuper de la cr茅ation...<pre><?phprequire_once('socket.php');class Telnet {<strong> function Telnet(&$network) { $this->_network = &$network; }</strong> ... function &connect($ip, $port, $username, $password) {<strong> $socket = &$this->_network->createSocket($ip, $port); $socket->read( ... );</strong> ... return $socket; }}?></pre> Il s'agit l脿 probablement de la r茅ponse la plus travaill茅e 茅tant donn茅 que la cr茅ation est maintenant situ茅e dans une petite classe sp茅cialis茅e. La fabrique r茅seau peut 锚tre test茅e s茅par茅ment et utilis茅e en tant que fantaisie quand nous testons la classe telnet...<pre>class TelnetTest extends UnitTestCase { ... function testConnection() {<strong> $socket = &new MockSocket($this); ... $network = &new MockNetwork($this); $network->setReturnReference('createSocket', $socket); $telnet = &new Telnet($network); $telnet->connect('127.0.0.1', 21, 'Me', 'Secret'); ...</strong> }}</pre> Le probl猫me reste que nous ajoutons beaucoup de classes 脿 la biblioth猫que. Et aussi que nous utilisons beaucoup de fabriques ce qui rend notre code un peu moins intuitif. La solution la plus flexible, mais aussi la plus complexe. </p> <p> Peut-on trouver un juste milieu ?
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?