PHPUnit测试私有属性和方法功能示例

本文实例讲述了PHPUnit测试私有属性方法功能分享给大家供大家参考,具体如下:

一、测试类中的私有方法

rush:PHP;"> class Sample { private $a = 0; private function run() { echo $a; } }

上面只是简单的写了一个类包含,一个私有变量和一个私有方法。对于protected和private方法,由于无法像是用public方法一样直接调用,所以在使用PHPunit进行单测的时候,多有不便,特别是当一个类中,对外只提供少量接口,内部使用了大量private方法的情况。

对于protected方法,建议使用继承的方式进行测试,在此就不再赘述。而对于private方法的测试,建议使用PHP的反射机制来进行。话不多说,上代码

setAccessible(true); //将run方法从private变成类似于public的权限 $method->invoke(new Sample()); //调用run方法 }

如果run方法是静态的,如:

rush:PHP;"> private static function run() { echo 'run is a private static function'; }

那么invoke函数还可以这么写:

invoke(null); //只有静态方法可以不必传类的实例化

如果run还需要传参,比如:

rush:PHP;"> private function run($x,$y) { return $x + $y; }

那么,测试代码可以改为:

invokeArgs(new Sample(),array(1,2)); //array中依次写入要传的参数。执行结果返回3

【注意】:利用反射的方法测试私有方法虽好,但setAccessible函数PHP5.3.2版本以后才支持的(>=5.3.2)

二、私有属性的get/set

说完了私有方法,再来看看私有属性,依旧拿Sample类作为例子,想要获取或设置Sample类中的私有属性$a的值可以用如下方法

getProperty('a'); $reflectedProperty->setAccessible(true); $reflectedProperty->getValue(); //获取$a的值 $reflectedProperty->setValue(123); //给$a赋值:$a = 123; }

上述方法对静态属性依然有效。

到此,是不是瞬间感觉测试私有方法属性变得很容易了。

附:PHPunit 测试私有方法(英文原文)

This article is part of a series on testing untestable code:

  • Testing private methods
  • Testing code that uses singletons
  • Stubbing static methods
  • Stubbing hard-coded dependencies

No,not those privates. If you need help with those,this book might help.

One question I get over and over again when talking about Unit Testing is this:

"How do I test the private attributes and methods of my objects?"

Lets assume we have a class Foo:

rush:PHP;"> bar = $this->doSomethingPrivate(); } private function doSomethingPrivate() { return 'blah'; } } ?>

Before we explore how protected and private attributes and methods can be tested directly,lets have a look at how they can be tested indirectly.

The following test calls the testDoSomething() method which in turn calls thedoSomethingPrivate() method:

rush:PHP;"> assertEquals('blah',$foo->doSomething()); } } ?>

The test above assumes that testDoSomething() only works correctly whentestDoSomethingPrivate() works correctly. This means that we have indirectly testedtestDoSomethingPrivate(). The problem with this approach is that when the test fails we do not kNow directly where the root cause for the failure is. It Could be in eithertestDoSomething() or testDoSomethingPrivate(). This makes the test less valuable.

PHPUnit supports reading protected and private attributes through thePHPUnit_Framework_Assert::readAttribute() method. Convenience wrappers such asPHPUnit_Framework_TestCase::assertAttributeEquals() exist to express assertions onprotected and private attributes:

rush:PHP;"> assertAttributeEquals( 'baz',/* expected value */ 'bar',/* attribute name */ new Foo /* object */ ); } } ?>

PHP 5.3.2 introduces the ReflectionMethod::setAccessible() method to allow the invocation of protected and private methods through the Reflection API:

rush:PHP;"> setAccessible(TRUE); $this->assertEquals( 'blah',$method->invoke(new Foo) ); } } ?>

In the test above we directly test testDoSomethingPrivate(). When it fails we immediately kNow where to look for the root cause.

I agree with Dave Thomas and Andy Hunt,who write in their book "Pragmatic Unit Testing":

"In general,you don't want to break any encapsulation for the sake of testing (or as Mom used to say,"don't expose your privates!"). Most of the time,you should be able to test a class by exercising its public methods. If there is significant functionality that is hidden behind private or protected access,that might be a warning sign that there's another class in there struggling to get out."

So: Just because the testing of protected and private attributes and methods is possible does not mean that this is a "good thing".

参考文献:

http://php.net/manual/en/class.reflectionmethod.php

更多关于PHP相关内容感兴趣的读者可查看本站专题:《》、《》、《》、《》、《》、《》、《》及《

希望本文所述对大家PHP程序设计有所帮助。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返回预支付订单号的接口,目前微信支付所有场景均使用这一接口。下面介绍的是其中NATIVE的支付实现流程与PC端实现扫码支付流程
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返回预支付订单号的接口,目前微信支付所有场景均使用这一接口。下面介绍的是其中APP的支付的配置与实现流程
前言 之前做了微信登录,所以总结一下微信授权登录并获取用户信息这个功能的开发流程。 配置 1.首先得在微信公众平台申请一下微信小程序账号并获取到小程序的AppID和AppSecret https://mp.weixin.qq.com/cgi-bin/loginpage?url=%2Fwxamp%2F
FastAdmin是我第一个接触的后台管理系统框架。FastAdmin是一款开源且免费商用的后台开发框架,它基于ThinkPHP和Bootstrap两大主流技术构建的极速后台开发框架,它有着非常完善且强大的功能和便捷的开发体验,使我逐渐喜欢上了它。
之前公司需要一个内部的通讯软件,就叫我做一个。通讯软件嘛,就离不开通讯了,然后我就想到了长连接。这里本人用的是GatewayWorker框架。
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返回预支付订单号的接口,目前微信支付所有场景均使用这一接口。下面介绍的是其中JSAPI的支付实现流程
服务器优化必备:深入了解PHP8底层开发原理
Golang的网络编程:如何快速构建高性能的网络应用?
Golang和其他编程语言的对比:为什么它的开发效率更高?
PHP8底层开发原理揭秘:如何利用新特性创建出色的Web应用
将字符重新排列以形成回文(如果可能)在C++中
掌握PHP8底层开发原理和新特性:创建高效可扩展的应用程序
服务器性能优化必学:掌握PHP8底层开发原理
PHP8新特性和底层开发原理详解:优化应用性能的终极指南
将 C/C++ 代码转换为汇编语言
深入研究PHP8底层开发原理:创建高效可扩展的应用程序
C++程序查找法向量和迹
PHP8底层开发原理实战指南:提升服务器效能
重排数组,使得当 i 为偶数时,arr[i] >= arr[j],当 i 为奇数时,arr[i] <= arr[j],其中 j < i,使用 C++ 语言实现
Golang的垃圾回收:为什么它可以减少开发人员的负担?