‘壹’ 如何在phpunit中mock一个单例类
当我们对A类进行单元测试时,A类可能依赖了B类,为了减少依赖,方便A类方法的测试,我们可以模拟一个B类,简单规定其各方法的返回值(而非真正实现具体逻辑)。Phpunit中提供了一套模拟类的api,简单使用如下:
[php] view
plainprint?
class StubTest extends PHPUnit_Framework_TestCase
{
public function testStub()
{
// Create a stub for the SomeClass class.
$stub = $this->getMock('SomeClass');
// Configure the stub.
$stub->expects($this->any())
->method('doSomething')
->will($this->returnValue('foo'));
// Calling $stub->doSomething() will now return
// 'foo'.
$this->assertEquals('foo', $stub->doSomething());
}
}
class StubTest extends PHPUnit_Framework_TestCase
{
public function testStub()
{
// Create a stub for the SomeClass class.
$stub = $this->getMock('SomeClass');
// Configure the stub.
$stub->expects($this->any())
->method('doSomething')
->will($this->returnValue('foo'));
// Calling $stub->doSomething() will now return
// 'foo'.
$this->assertEquals('foo', $stub->doSomething());
}
}
在这个例子中,我们得到了一个'SomeClass'的模拟,规定其可以被调用任意次,如果调用doSomething方法,将得到值foo。
问题:
我们知道,对于一个单例类,其constructor方法为private,而getMock的实现,默认是要调用原类的constructor方法。
如果SomeClass为单例,phpunit将会提示
Call to private SomeClass::__construct() from context 'PHPUnit_Framework_TestCase'
这时,我们的测试该如何进行呢?
解决:
仍然使用getMock进行模拟。
只要将其第5个参数设为false即可。其含意是:不调用原对象的构造函数。
[php] view
plainprint?
$stub = $this->getMock('SomeClass', array(), array(), '', false);
$stub = $this->getMock('SomeClass', array(), array(), '', false);
不得不说,这样使用有点复杂。
如果你使用的是phpunit3.5及以上版本提供了更易用的api,你可以这样禁掉对原有constructor方法的调用。
$stub=$this->getMockBuilder('SomeClass')->disableOriginalConstructor()->getMock();
附:
对getMock的6个可选参数的详解,
手册中并未提及它们的默认值,经测试得到结果如下:
array(), array(), '', false, false, false
即
$stub=$this->getMockBuilder('SomeClass')
等同于:
$stub=$this->getMockBuilder('SomeClass',array(), array(), '', true, false, false)
‘贰’ 如何对子方法中的对象进行mock
在进行对象方法的引用时,方法中参数的个数,参数的数据类型与原方法中定义的要一致,否则编译器会出错。注意构造方法后面括号内带几个参数或者不带参数
‘叁’ mock 中如何模拟任意的数组
第一种方法是使用特殊设计的字符参数来模拟数组。
我们可以用 varchar 数据类型来模拟一个数组,数组中的元素用逗号分隔开,接着通过WHILE循环使用CHARINDEX以及SUBSTRING函数来提取其中的元素。
示例代码如下:
CREATE PROCEDURE sum_of_array @list varchar(1000)
AS
DECLARE @ix int, @pos int, @str varchar(1000), @sum int
SET @pos = 1
SET @ix = 1
SET @sum = 0
WHILE @ix > 0
BEGIN
SET @ix = charindex(',', @list, @pos)
IF @ix > 0
SET @str = substring(@list, @pos, @ix - @pos)
ELSE
SET @str = substring(@list, @pos, len(@list))
SET @str = ltrim(rtrim(@str))
SET @sum = @sum + cast(@str AS int)
SET @pos = @ix + 1
END
SELECT @sum
GO
该示例代码可以求出一个整型数据数组的和,调用方式为:
EXEC sum_of_array @list = '1,2,3,4,5'
结果为:16。
‘肆’ 如何mock调用super的方法
据我说知: mock测试方法用于构造对象,而不是你说的方法 比如,你现在要调用数据库,但这块也许还没完成,无法用orm框架进行映射,你就可以先new一些这样的对象,将它们保存或当作参数传入等 比如某接口中(UserDao)你有一个方法叫:queryUser(S...
‘伍’ 如何mock静态方法
因为Mockito使用继承的方式实现mock的,用CGLIB生成mock对象代替真实的对象进行执行,为了mock实例的方法,你可以在subclass中覆盖它,而static方法是不能被子类覆盖的,所以Mockito不能mock静态方法。
但PowerMock可以mock静态方法,因为它直接在bytecode上工作,类似这样:
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.moles.testng.PowerMockTestCase;
import org.testng.Assert;
import org.testng.annotations.Test;
@PrepareForTest(AbstractAnimal.class)
public class AbstractAnimalTest extends PowerMockTestCase {
‘陆’ 如何将Spring配置文件已配置的类Mock
只有设置了start-up属性才会被容器启动,调用其init方法。如果你不需要容器启动时调用servlet,就把start-up属性注掉。spring配置在listener节点中,在容器启动时会首先初始化spring