单元测试/类间谍

一个简单的特性,用于在单元测试中辅助测试受保护类方法

v1.0.0 2015-02-27 21:53 UTC

This package is not auto-updated.

Last update: 2024-09-14 16:19:23 UTC


README

在某些情况下,你可能想在不需要像 https://github.com/padraic/mockery 这样的测试工具的情况下模拟类的方法。这个特性将允许你这样做。

安装

  • composer require --dev unit-testing/class-spy:dev-master
  • 或者在 composer.json 文件的 require-dev 块中添加 "unit-testing/class-spy": "dev-master",然后运行 composer update

用法

在你的 PHPUnit 测试中,你将为要测试的类创建一个存根。在该存根定义中,添加 use \UnitTesting\ClassSpy\WatchableTrait;。你的存根将扩展以下方法

  • trackMethodCall:对于你想要在存根上测试的任何方法,你可以在方法内部调用 return $this->trackMethodCall(); 来创建(或覆盖其父方法)。
  • getAllMethodCalls:返回所有跟踪方法的所有参数的数组。该数组以方法名称为键,方法传递的参数数组为值。
  • getMethodCalls($method, $index = null):传递方法名称以获取传递给它的参数。可选地添加索引(其中 1 = 第一次调用)以获取特定调用的参数,如果方法被多次调用。如果该参数从未被调用,或者调用的次数少于提供的索引,则返回 null。
  • getLastMethodCall($method):获取特定方法的最后参数集。
  • setMethodResult($method, $result):模拟特定方法返回的结果。如果 $result 参数是 Closure 实例,则执行该闭包并返回其实例的结果。

上述所有方法都有静态类方法的等效方法:trackStaticMethodCallgetAllStaticMethodCallsgetStaticMethodCallsgetLastStaticMethodCallsetStaticMethodResult

示例

<?php namespace UnitTesting\ClassSpy;

class WatchableTraitIntegrationTest extends \PHPUnit_Framework_TestCase {

	function test_WatchableTrait_TracksCalls()
	{
		$instance = new SomeTestClassStub;

		// let's make some calls to this method
		$instance->doSomething('foo');
		$instance->doSomething();
		$instance->doSomethingElse('zee');
		$instance->doSomething('baz', 'boo');

		// all the tracked method and their arguments can be retrieved with getAllMethodCalls()
		$this->assertEquals(array(
			'doSomething' => array(
				array('foo'),
				array(),
				array('baz', 'boo'),
			),
			'doSomethingElse' => array(
				array('zee'),
			),
		), $instance->getAllMethodCalls());

		// get a specific method's argument calls
		$this->assertEquals(array(
			array('foo'),
			array(),
			array('baz', 'boo'),
		), $instance->getMethodCalls('doSomething'));

		// get a specific method's argument calls with an index, remember 2 = second call
		$this->assertEquals(array(), $instance->getMethodCalls('doSomething', 2));

		// get the last argument call
		$this->assertEquals(array('baz', 'boo'), $instance->getMethodCalls('doSomething', 'last'));

		// another way to do the above
		$this->assertEquals(array('baz', 'boo'), $instance->getLastMethodCall('doSomething'));

		// trying to access a call on a tracked method with an index beyond the actual number of calls yields null
		$this->assertNull($instance->getMethodCalls('doSomething', 100));

		// something that is never called will yield null
		$this->assertNull($instance->getMethodCalls('doSomethingThatIsNotTracked'));
	}

	function test_WatchableTraitOnStatic_TracksCalls()
	{
		// let's make some calls to this method
		SomeTestClassStub::doSomethingStatic('foo');
		SomeTestClassStub::doSomethingStatic();
		SomeTestClassStub::doSomethingStatic('baz', 'boo');

		// all the tracked method and their arguments can be retrieved with getAllMethodCalls()
		$this->assertEquals(array(
			'doSomethingStatic' => array(
				array('foo'),
				array(),
				array('baz', 'boo'),
			),
		), SomeTestClassStub::getAllStaticMethodCalls());

		// don't forget to reset calls on a static for subsequent tests
		SomeTestClassStub::flushStatic();
	}

	function test_WatchableTrait_CanSetResponses()
	{
		$instance = new SomeTestClassStub;
		// let's set up a simple response
		$instance->setMethodResult('doSomething', 'same result every time');

		// it will always return same thing
		$this->assertEquals('same result every time', $instance->doSomething());
		$this->assertEquals('same result every time', $instance->doSomething('foo'));
		$this->assertEquals('same result every time', $instance->doSomething('foo', 'bar'));

		// return something based upon the parameter
		$instance->setMethodResult('doSomething', function($param)
		{
			return $param . ' result';
		});

		// it will now return value based upon our closure
		$this->assertEquals('foo result', $instance->doSomething('foo'));
		$this->assertEquals('bar result', $instance->doSomething('bar'));
	}
}

class SomeTestClassStub {
	// add this trait to set this class up for testing
	use \UnitTesting\ClassSpy\WatchableTrait;

	public function doSomething()
	{
		// this will actuall track the method and its arguments.
		// Be sure to return its value if you want to mock some return values.
		return $this->trackMethodCall();
	}

	public function doSomethingElse()
	{
		// we'll just set up another one the same as above for illustration purposes.
		return $this->trackMethodCall();
	}

	public static function doSomethingStatic()
	{
		// we'll do the same for a static method
		return self::trackStaticMethodCall();
	}
}