From 64d8af61a64db0b00d498800e1f20e62b4473329 Mon Sep 17 00:00:00 2001 From: Dmitry Naumenko Date: Thu, 19 Oct 2017 01:54:40 +0300 Subject: [PATCH] Fixes for PHP 7.2 compatibility (#14959) --- .travis.yml | 12 +++++-- framework/db/ActiveQuery.php | 4 ++- framework/di/Container.php | 4 +-- framework/i18n/Formatter.php | 9 +++++- framework/validators/EmailValidator.php | 15 +++++++-- framework/validators/UniqueValidator.php | 2 +- framework/validators/UrlValidator.php | 12 ++++++- framework/web/User.php | 2 +- phpunit.xml.dist | 3 +- tests/ResultPrinter.php | 38 +++++++++++++++++++++++ tests/compatibility.php | 20 ++++++++++-- tests/framework/ar/ActiveRecordTestTrait.php | 3 +- tests/framework/db/GetTablesAliasTestTrait.php | 2 +- tests/framework/di/InstanceTest.php | 3 +- tests/framework/filters/PageCacheTest.php | 2 +- tests/framework/filters/RateLimiterTest.php | 3 +- tests/framework/helpers/ArrayHelperTest.php | 8 +++-- tests/framework/helpers/HtmlTest.php | 23 ++++++++------ tests/framework/helpers/JsonTest.php | 2 +- tests/framework/i18n/FormatterTest.php | 30 ++++++++++++++---- tests/framework/i18n/IntlTestHelper.php | 10 +++++- tests/framework/rest/DataFilterTest.php | 4 +-- tests/framework/validators/FileValidatorTest.php | 10 ++++-- tests/framework/validators/data/mimeType/test.xml | 10 ++++-- tests/framework/widgets/ActiveFormTest.php | 2 +- 25 files changed, 185 insertions(+), 48 deletions(-) create mode 100644 tests/ResultPrinter.php diff --git a/.travis.yml b/.travis.yml index 6cb02ed..679f8f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,9 +55,9 @@ addons: matrix: fast_finish: true include: - # run tests coverage on PHP 7.1 - php: 7.2 + # run tests coverage on PHP 7.1 - php: 7.1 env: TASK_TESTS_COVERAGE=1 @@ -110,7 +110,6 @@ matrix: allow_failures: - php: nightly - - php: 7.2 install: - | @@ -178,6 +177,15 @@ before_script: PHPUNIT_FLAGS="--coverage-clover=coverage.clover" fi + # Disable DEPRECATE messages during PHPUnit initialization on PHP 7.2. To fix them, PHPUnit should be updated to 6.* + # For Yii2 tests, messages will be enabled by tests/bootstrap.php + - | + if [ $TRAVIS_PHP_VERSION == 7.2 ]; then + echo 'Disabled DEPRECATED notifications for PHP 7.2'; + echo 'error_reporting = E_ALL & ~E_DEPRECATED' >> /tmp/php-config.ini; + phpenv config-add /tmp/php-config.ini; + fi + script: # PHP tests diff --git a/framework/db/ActiveQuery.php b/framework/db/ActiveQuery.php index 8392e98..c83684c 100644 --- a/framework/db/ActiveQuery.php +++ b/framework/db/ActiveQuery.php @@ -759,7 +759,9 @@ class ActiveQuery extends Query implements ActiveQueryInterface */ public function viaTable($tableName, $link, callable $callable = null) { - $relation = new self(get_class($this->primaryModel), [ + $modelClass = $this->primaryModel !== null ? get_class($this->primaryModel) : get_class(); + + $relation = new self($modelClass, [ 'from' => [$tableName], 'link' => $link, 'multiple' => true, diff --git a/framework/di/Container.php b/framework/di/Container.php index eed2aa8..2181a78 100644 --- a/framework/di/Container.php +++ b/framework/di/Container.php @@ -624,7 +624,7 @@ class Container extends Component public function setDefinitions(array $definitions) { foreach ($definitions as $class => $definition) { - if (count($definition) === 2 && array_values($definition) === $definition) { + if (is_array($definition) && count($definition) === 2 && array_values($definition) === $definition) { $this->set($class, $definition[0], $definition[1]); continue; } @@ -646,7 +646,7 @@ class Container extends Component public function setSingletons(array $singletons) { foreach ($singletons as $class => $definition) { - if (count($definition) === 2 && array_values($definition) === $definition) { + if (is_array($definition) && count($definition) === 2 && array_values($definition) === $definition) { $this->setSingleton($class, $definition[0], $definition[1]); continue; } diff --git a/framework/i18n/Formatter.php b/framework/i18n/Formatter.php index 842cc99..33247bd 100644 --- a/framework/i18n/Formatter.php +++ b/framework/i18n/Formatter.php @@ -1529,7 +1529,14 @@ class Formatter extends Component $multipliers = array_values($this->measureUnits[$unitType][$unitSystem]); - list($params, $position) = $this->formatNumber($value * $baseUnit, $decimals, null, $multipliers, $options, $textOptions); + list($params, $position) = $this->formatNumber( + $this->normalizeNumericValue($value) * $baseUnit, + $decimals, + null, + $multipliers, + $options, + $textOptions + ); $message = $this->getUnitMessage($unitType, $unitFormat, $unitSystem, $position); diff --git a/framework/validators/EmailValidator.php b/framework/validators/EmailValidator.php index bd613f6..2c57f28 100644 --- a/framework/validators/EmailValidator.php +++ b/framework/validators/EmailValidator.php @@ -76,8 +76,8 @@ class EmailValidator extends Validator $valid = false; } else { if ($this->enableIDN) { - $matches['local'] = idn_to_ascii($matches['local']); - $matches['domain'] = idn_to_ascii($matches['domain']); + $matches['local'] = $this->idnToAscii($matches['local']); + $matches['domain'] = $this->idnToAscii($matches['domain']); $value = $matches['name'] . $matches['open'] . $matches['local'] . '@' . $matches['domain'] . $matches['close']; } @@ -104,6 +104,17 @@ class EmailValidator extends Validator return $valid ? null : [$this->message, []]; } + + private function idnToAscii($idn) + { + if (PHP_VERSION_ID < 50600) { + // TODO: drop old PHP versions support + return idn_to_ascii($idn); + } + + return idn_to_ascii($idn, 0, INTL_IDNA_VARIANT_UTS46); + } + /** * @inheritdoc */ diff --git a/framework/validators/UniqueValidator.php b/framework/validators/UniqueValidator.php index c4e3b83..41cb179 100644 --- a/framework/validators/UniqueValidator.php +++ b/framework/validators/UniqueValidator.php @@ -132,7 +132,7 @@ class UniqueValidator extends Validator } if ($this->modelExists($targetClass, $conditions, $model)) { - if (count($targetAttribute) > 1) { + if (is_array($targetAttribute) && count($targetAttribute) > 1) { $this->addComboNotUniqueError($model, $attribute); } else { $this->addError($model, $attribute, $this->message); diff --git a/framework/validators/UrlValidator.php b/framework/validators/UrlValidator.php index 6f237a2..2eeb99f 100644 --- a/framework/validators/UrlValidator.php +++ b/framework/validators/UrlValidator.php @@ -96,7 +96,7 @@ class UrlValidator extends Validator if ($this->enableIDN) { $value = preg_replace_callback('/:\/\/([^\/]+)/', function ($matches) { - return '://' . idn_to_ascii($matches[1]); + return '://' . $this->idnToAscii($matches[1]); }, $value); } @@ -108,6 +108,16 @@ class UrlValidator extends Validator return [$this->message, []]; } + private function idnToAscii($idn) + { + if (PHP_VERSION_ID < 50600) { + // TODO: drop old PHP versions support + return idn_to_ascii($idn); + } + + return idn_to_ascii($idn, 0, INTL_IDNA_VARIANT_UTS46); + } + /** * @inheritdoc */ diff --git a/framework/web/User.php b/framework/web/User.php index 1b430e0..abf1973 100644 --- a/framework/web/User.php +++ b/framework/web/User.php @@ -561,7 +561,7 @@ class User extends Component return null; } $data = json_decode($value, true); - if (count($data) == 3) { + if (is_array($data) && count($data) == 3) { list($id, $authKey, $duration) = $data; /* @var $class IdentityInterface */ $class = $this->identityClass; diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 4dc2775..16c799e 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -5,7 +5,8 @@ convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" - stopOnFailure="false"> + stopOnFailure="false" + printerClass="yiiunit\ResultPrinter"> ./tests diff --git a/tests/ResultPrinter.php b/tests/ResultPrinter.php new file mode 100644 index 0000000..d9a8b51 --- /dev/null +++ b/tests/ResultPrinter.php @@ -0,0 +1,38 @@ +out !== STDOUT) { + parent::flush(); + } + } +} diff --git a/tests/compatibility.php b/tests/compatibility.php index 9f881f3..82d0d4b 100644 --- a/tests/compatibility.php +++ b/tests/compatibility.php @@ -17,10 +17,26 @@ namespace PHPUnit\Framework\Constraint { } } +namespace PHPUnit\TextUI { + if (!class_exists('\PHPUnit\TextUI\ResultPrinter') && class_exists('PHPUnit_TextUI_ResultPrinter')) { + class ResultPrinter extends \PHPUnit_TextUI_ResultPrinter + { + + } + } +} + +namespace PHPUnit\Framework\Error { + if (!class_exists('PHPUnit\Framework\Error\Notice') && class_exists('PHPUnit_Framework_Error_Notice')) { + class Notice extends \PHPUnit_Framework_Error_Notice + { + + } + } +} + namespace PHPUnit\Framework { if (!class_exists('PHPUnit\Framework\TestCase') && class_exists('PHPUnit_Framework_TestCase')) { - echo "Applying compatibility patch for PHPUnit 6...\n"; - abstract class TestCase extends \PHPUnit_Framework_TestCase { /** diff --git a/tests/framework/ar/ActiveRecordTestTrait.php b/tests/framework/ar/ActiveRecordTestTrait.php index 5ffd10f..e74f6fa 100644 --- a/tests/framework/ar/ActiveRecordTestTrait.php +++ b/tests/framework/ar/ActiveRecordTestTrait.php @@ -84,8 +84,7 @@ trait ActiveRecordTestTrait $customer = $customerClass::findOne(5); $this->assertNull($customer); $customer = $customerClass::findOne(['id' => [5, 6, 1]]); - // can't use assertCount() here since it will count model attributes instead - $this->assertEquals(1, count($customer)); + $this->assertInstanceOf($customerClass, $customer); $customer = $customerClass::find()->where(['id' => [5, 6, 1]])->one(); $this->assertNotNull($customer); diff --git a/tests/framework/db/GetTablesAliasTestTrait.php b/tests/framework/db/GetTablesAliasTestTrait.php index ece065f..d59108d 100644 --- a/tests/framework/db/GetTablesAliasTestTrait.php +++ b/tests/framework/db/GetTablesAliasTestTrait.php @@ -56,7 +56,7 @@ trait GetTablesAliasTestTrait $query = $this->createQuery(); $query->from = new \stdClass(); - $this->setExpectedException('\yii\base\InvalidConfigException'); + $this->expectException('\yii\base\InvalidConfigException'); $query->getTablesUsedInFrom(); } diff --git a/tests/framework/di/InstanceTest.php b/tests/framework/di/InstanceTest.php index 5e93733..e93b173 100644 --- a/tests/framework/di/InstanceTest.php +++ b/tests/framework/di/InstanceTest.php @@ -193,7 +193,8 @@ PHP public function testExceptionInvalidDataTypeInArray() { - $this->setExpectedException('yii\base\InvalidConfigException', 'Invalid data type: yii\db\Connection. yii\base\Widget is expected.'); + $this->expectException('yii\base\InvalidConfigException'); + $this->expectExceptionMessage('Invalid data type: yii\db\Connection. yii\base\Widget is expected.'); Instance::ensure([ 'class' => Connection::className(), ], 'yii\base\Widget'); diff --git a/tests/framework/filters/PageCacheTest.php b/tests/framework/filters/PageCacheTest.php index 9a645d1..7f674a4 100644 --- a/tests/framework/filters/PageCacheTest.php +++ b/tests/framework/filters/PageCacheTest.php @@ -166,7 +166,7 @@ class PageCacheTest extends TestCase Yii::$app->response->cookies->add(new Cookie([ 'name' => $name, 'value' => $value, - 'expire' => PHP_INT_MAX, + 'expire' => strtotime('now +1 year'), ])); $cookies[$name] = $value; } diff --git a/tests/framework/filters/RateLimiterTest.php b/tests/framework/filters/RateLimiterTest.php index e6f0333..895102f 100644 --- a/tests/framework/filters/RateLimiterTest.php +++ b/tests/framework/filters/RateLimiterTest.php @@ -15,6 +15,7 @@ use yii\web\Request; use yii\web\Response; use yii\web\User; use yiiunit\framework\filters\stubs\RateLimit; +use yiiunit\framework\filters\stubs\UserIdentity; use yiiunit\TestCase; /** @@ -117,7 +118,7 @@ class RateLimiterTest extends TestCase ->setAllowance([1, time() + 2]); $rateLimiter = new RateLimiter(); - $this->setExpectedException('yii\web\TooManyRequestsHttpException'); + $this->expectException('yii\web\TooManyRequestsHttpException'); $rateLimiter->checkRateLimit($rateLimit, Yii::$app->request, Yii::$app->response, 'testAction'); } diff --git a/tests/framework/helpers/ArrayHelperTest.php b/tests/framework/helpers/ArrayHelperTest.php index fa5f46e..f4816b9 100644 --- a/tests/framework/helpers/ArrayHelperTest.php +++ b/tests/framework/helpers/ArrayHelperTest.php @@ -56,7 +56,7 @@ class ArrayHelperTest extends TestCase public function testToArray() { - $dataArrayable = $this->getMock('yii\\base\\Arrayable'); + $dataArrayable = $this->getMockBuilder('yii\\base\\Arrayable')->getMock(); $dataArrayable->method('toArray')->willReturn([]); $this->assertEquals([], ArrayHelper::toArray($dataArrayable)); $this->assertEquals(['foo'], ArrayHelper::toArray('foo')); @@ -810,20 +810,22 @@ class ArrayHelperTest extends TestCase /** * This is expected to result in a PHP error. - * @expectedException \PHPUnit_Framework_Error + * @requires PHPUnit 6.0 */ public function testGetValueNonexistingProperties1() { + $this->expectException('PHPUnit\Framework\Error\Notice'); $object = new Post1(); $this->assertEquals(null, ArrayHelper::getValue($object, 'nonExisting')); } /** * This is expected to result in a PHP error. - * @expectedException \PHPUnit_Framework_Error + * @requires PHPUnit 6.0 */ public function testGetValueNonexistingProperties2() { + $this->expectException('PHPUnit\Framework\Error\Notice'); $arrayObject = new \ArrayObject(['id' => 23], \ArrayObject::ARRAY_AS_PROPS); $this->assertEquals(23, ArrayHelper::getValue($arrayObject, 'nonExisting')); } diff --git a/tests/framework/helpers/HtmlTest.php b/tests/framework/helpers/HtmlTest.php index 5b69c32..e4e22e2 100644 --- a/tests/framework/helpers/HtmlTest.php +++ b/tests/framework/helpers/HtmlTest.php @@ -140,12 +140,17 @@ class HtmlTest extends TestCase public function testCsrfMetaTagsEnableCsrfValidationWithoutCookieValidationKey() { - $request = $this->getMock('yii\\web\\Request'); - $request->method('enableCsrfValidation')->willReturn(true); - Yii::$app->set('request', $request); - $pattern = '%A'; - $actual = Html::csrfMetaTags(); - $this->assertStringMatchesFormat($pattern, $actual); + $this->mockApplication([ + 'components' => [ + 'request' => [ + 'class' => 'yii\web\Request', + 'enableCsrfValidation' => true, + ] + ], + ]); + $this->expectException('yii\base\InvalidConfigException'); + $this->expectExceptionMessage('yii\web\Request::cookieValidationKey must be configured with a secret key.'); + Html::csrfMetaTags(); } /** @@ -1458,7 +1463,7 @@ EOD; $actual = Html::getAttributeValue($model, 'types'); $this->assertSame($expected, $actual); - $activeRecord = $this->getMock('yii\\db\\ActiveRecordInterface'); + $activeRecord = $this->getMockBuilder('yii\\db\\ActiveRecordInterface')->getMock(); $activeRecord->method('getPrimaryKey')->willReturn(1); $model->types = $activeRecord; @@ -1491,14 +1496,14 @@ EOD; */ public function testGetInputNameInvalidParamExceptionFormName() { - $model = $this->getMock('yii\\base\\Model'); + $model = $this->getMockBuilder('yii\\base\\Model')->getMock(); $model->method('formName')->willReturn(''); Html::getInputName($model, '[foo]bar'); } public function testGetInputName() { - $model = $this->getMock('yii\\base\\Model'); + $model = $this->getMockBuilder('yii\\base\\Model')->getMock(); $model->method('formName')->willReturn(''); $expected = 'types'; $actual = Html::getInputName($model, 'types'); diff --git a/tests/framework/helpers/JsonTest.php b/tests/framework/helpers/JsonTest.php index a50ae03..7c0ef3e 100644 --- a/tests/framework/helpers/JsonTest.php +++ b/tests/framework/helpers/JsonTest.php @@ -30,7 +30,7 @@ class JsonTest extends TestCase public function testEncode() { // Arrayable data encoding - $dataArrayable = $this->getMock('yii\\base\\Arrayable'); + $dataArrayable = $this->getMockBuilder('yii\\base\\Arrayable')->getMock(); $dataArrayable->method('toArray')->willReturn([]); $actual = Json::encode($dataArrayable); $this->assertSame('{}', $actual); diff --git a/tests/framework/i18n/FormatterTest.php b/tests/framework/i18n/FormatterTest.php index b44339b..b7d502f 100644 --- a/tests/framework/i18n/FormatterTest.php +++ b/tests/framework/i18n/FormatterTest.php @@ -237,7 +237,8 @@ class FormatterTest extends TestCase ], [ 'Wrong value is casted properly', - ['NaN'], '0 millimeters', '0 mm' + ['NaN'], '0 millimeters', '0 mm', + ['yii\base\InvalidParamException', "'NaN' is not a numeric value"] ], [ 'Negative value works', @@ -293,18 +294,26 @@ class FormatterTest extends TestCase /** * @dataProvider lengthDataProvider */ - public function testIntlAsLength($message, $arguments, $expected) + public function testIntlAsLength($message, $arguments, $expected, $_shortLength, $expectedException = []) { $this->ensureIntlUnitDataIsAvailable(); + if ($expectedException !== []) { + $this->expectException($expectedException[0]); + $this->expectExceptionMessage($expectedException[1]); + } $this->assertSame($expected, call_user_func_array([$this->formatter, 'asLength'], $arguments), 'Failed asserting that ' . $message); } /** * @dataProvider lengthDataProvider */ - public function testIntlAsShortLength($message, $arguments, $_, $expected) + public function testIntlAsShortLength($message, $arguments, $_length, $expected, $expectedException = []) { $this->ensureIntlUnitDataIsAvailable(); + if ($expectedException !== []) { + $this->expectException($expectedException[0]); + $this->expectExceptionMessage($expectedException[1]); + } $this->assertSame($expected, call_user_func_array([$this->formatter, 'asShortLength'], $arguments), 'Failed asserting that ' . $message); } @@ -317,7 +326,8 @@ class FormatterTest extends TestCase ], [ 'Wrong value is casted properly', - ['NaN'], '0 grams', '0 g' + ['NaN'], '0 grams', '0 g', + ['yii\base\InvalidParamException', "'NaN' is not a numeric value"] ], [ 'Negative value works', @@ -373,18 +383,26 @@ class FormatterTest extends TestCase /** * @dataProvider weightDataProvider */ - public function testIntlAsWeight($message, $arguments, $expected) + public function testIntlAsWeight($message, $arguments, $expected, $_shortWeight, $expectedException = []) { $this->ensureIntlUnitDataIsAvailable(); + if ($expectedException !== []) { + $this->expectException($expectedException[0]); + $this->expectExceptionMessage($expectedException[1]); + } $this->assertSame($expected, call_user_func_array([$this->formatter, 'asWeight'], $arguments), 'Failed asserting that ' . $message); } /** * @dataProvider weightDataProvider */ - public function testIntlAsShortWeight($message, $arguments, $_, $expected) + public function testIntlAsShortWeight($message, $arguments, $_weight, $expected, $expectedException = []) { $this->ensureIntlUnitDataIsAvailable(); + if ($expectedException !== []) { + $this->expectException($expectedException[0]); + $this->expectExceptionMessage($expectedException[1]); + } $this->assertSame($expected, call_user_func_array([$this->formatter, 'asShortWeight'], $arguments), 'Failed asserting that ' . $message); } diff --git a/tests/framework/i18n/IntlTestHelper.php b/tests/framework/i18n/IntlTestHelper.php index b6a23df..5720309 100644 --- a/tests/framework/i18n/IntlTestHelper.php +++ b/tests/framework/i18n/IntlTestHelper.php @@ -24,10 +24,18 @@ namespace yiiunit\framework\i18n { { static::$enableIntl = null; if (strncmp($test->getName(false), 'testIntl', 8) === 0) { + static::$enableIntl = true; + + if (version_compare(PHP_VERSION, '7.2.0.RC.1', '>=') && version_compare(PHP_VERSION, '7.2.0.RC.3', '<=')) { + // IntlDateFormatter::parse() is broken in PHP 7.2. Disabled INTL tests until regression is fixed: + // https://bugs.php.net/bug.php?id=75378 + $test->markTestSkipped('intl extension is broken in PHP 7.2'); + return; + } + if (!extension_loaded('intl')) { $test->markTestSkipped('intl extension is not installed.'); } - static::$enableIntl = true; } else { static::$enableIntl = false; } diff --git a/tests/framework/rest/DataFilterTest.php b/tests/framework/rest/DataFilterTest.php index a8d22a9..2d49613 100644 --- a/tests/framework/rest/DataFilterTest.php +++ b/tests/framework/rest/DataFilterTest.php @@ -49,7 +49,7 @@ class DataFilterTest extends TestCase $model = $builder->getSearchModel(); $this->assertTrue($model instanceof DynamicModel); - $this->setExpectedException('yii\base\InvalidConfigException'); + $this->expectException('yii\base\InvalidConfigException'); $builder->setSearchModel(new \stdClass()); } @@ -345,4 +345,4 @@ class DataFilterTest extends TestCase $this->assertEquals('Test message callback', $errorMessages['unsupportedOperatorType']); $this->assertTrue(isset($errorMessages['unknownAttribute'])); } -} \ No newline at end of file +} diff --git a/tests/framework/validators/FileValidatorTest.php b/tests/framework/validators/FileValidatorTest.php index 4cbd7fe..58468d0 100644 --- a/tests/framework/validators/FileValidatorTest.php +++ b/tests/framework/validators/FileValidatorTest.php @@ -388,15 +388,19 @@ class FileValidatorTest extends TestCase public function validMimeTypes() { - return [ + return array_filter([ ['test.svg', 'image/*', 'svg'], ['test.jpg', 'image/*', 'jpg'], ['test.png', 'image/*', 'png'], ['test.png', 'IMAGE/*', 'png'], ['test.txt', 'text/*', 'txt'], - ['test.xml', '*/xml', 'xml'], + // Disabled for PHP 7.2 RC because of regression: + // https://bugs.php.net/bug.php?id=75380 + version_compare(PHP_VERSION, '7.2.0.RC.1', '>=') && version_compare(PHP_VERSION, '7.2.0.RC.3', '<=') + ? null + : ['test.xml', '*/xml', 'xml'], ['test.odt', 'application/vnd*', 'odt'], - ]; + ]); } public function invalidMimeTypes() diff --git a/tests/framework/validators/data/mimeType/test.xml b/tests/framework/validators/data/mimeType/test.xml index 5011f28..2d818fa 100644 --- a/tests/framework/validators/data/mimeType/test.xml +++ b/tests/framework/validators/data/mimeType/test.xml @@ -1,2 +1,8 @@ - - \ No newline at end of file + + + + SilverFire + World + Hello, world! + + diff --git a/tests/framework/widgets/ActiveFormTest.php b/tests/framework/widgets/ActiveFormTest.php index 5074ec1..cd6cc7f 100644 --- a/tests/framework/widgets/ActiveFormTest.php +++ b/tests/framework/widgets/ActiveFormTest.php @@ -116,7 +116,7 @@ HTML $model = new DynamicModel(['name']); $model->addRule(['name'], 'required'); - $view = $this->getMock(View::className()); + $view = $this->getMockBuilder(View::className())->getMock(); $view->method('registerJs')->with($this->matches("jQuery('#w0').yiiActiveForm([], {\"validateOnSubmit\":false});")); $view->method('registerAssetBundle')->willReturn(true);