Сбой тестирования Laravel с «… ReflectionException: конфигурация класса не существует …»

#laravel #phpunit #config

#laravel #phpunit #конфигурация

Вопрос:

Я искал StackOverflow и в Интернете перепробовал все, что я там нашел, чтобы решить проблему, указанную ниже, но безрезультатно. Ошибка возникает только во время тестирования phpunit. Если запустить приложение Laravel (php artisan serve), оно работает нормально.

Вот подробности:

Я нахожусь на Win7 под управлением cygwin. Я использую composer.json, созданный в проекте php artisan create.

 Cygwin (win 7)
Runtime: PHP 7.4.8
PHPUnit 9.3.7 by Sebastian Bergmann and contributors.
Laravel Framework 7.26.0
  

Вот мой composer.json, который, я думаю, был изначально создан «php artisan create project» или что-то в этом роде.

 $ cat composer.json
{
    "name": "rubens-gomes/rubens-gomes.com",
    "type": "project",
    "description": "rubens-gomes.com Web Site",
    "homepage": "https://rubens-gomes.com",
    "keywords": [
        "framework",
        "laravel"
    ],
    "license": "PROPRIETARY",
    "authors": [
        {
            "name": "Rubens Gomes",
            "email": "rubens.s.gomes@gmail.com",
            "homepage": "https://rubens-gomes.com",
            "role": "Developer"
        }
    ],
    "support": {
        "email": "rubens.s.gomes@gmail.com"
    },
    "require": {
        "php": ">=7.4",
        "fideloper/proxy": "^4.2",
        "fruitcake/laravel-cors": "^2.0",
        "google/recaptcha": "^1.2",
        "guzzlehttp/guzzle": "^6.3",
        "laravel/framework": "^7.24",
        "laravel/tinker": "^2.0"
    },
    "require-dev": {
        "facade/ignition": "^2.0",
        "fzaninotto/faker": "^1.9.1",
        "mockery/mockery": "^1.3.1",
        "nunomaduro/collision": "^4.1",
        "phpunit/phpunit": "^9.2"
    },
    "config": {
        "optimize-autoloader": true,
        "preferred-install": "dist",
        "sort-packages": true
    },
    "extra": {
        "laravel": {
            "dont-discover": []
        }
    },
    "autoload": {
        "psr-4": {
            "App\": "app/"
        },
        "classmap": [
            "database/seeds",
            "database/factories"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\": "tests/"
        }
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "scripts": {
        "post-autoload-dump": [
            "Illuminate\Foundation\ComposerScripts::postAutoloadDump",
            "@php artisan package:discover --ansi"
        ],
        "post-root-package-install": [
            "@php -r "file_exists('.env') || copy('.env.example', '.env');""
        ],
        "post-create-project-cmd": [
            "@php artisan key:generate --ansi"
        ],
        "post-update-cmd": "@composer dump-autoload"
    }
}
  

Ниже мой phpunit.xml . Я пробовал другой загрузчик, но безрезультатно.

 <?xml version="1.0" encoding="UTF-8"?>
<phpunit
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
  <!--  bootstrap="vendor/autoload.php" -->
  bootstrap="bootstrap/app.php"
  colors="true"
  verbose="true">
  <coverage processUncoveredFiles="true">
    <include>
      <directory suffix=".php">./app</directory>
    </include>
  </coverage>
  <testsuites>
    <testsuite name="Unit">
      <directory suffix="Test.php">./tests/Unit</directory>
    </testsuite>
    <testsuite name="Feature">
      <directory suffix="Test.php">./tests/Feature</directory>
    </testsuite>
  </testsuites>
  <php>
    <server name="APP_ENV" value="testing"/>
    <server name="BCRYPT_ROUNDS" value="4"/>
    <server name="CACHE_DRIVER" value="array"/>
    <server name="MAIL_MAILER" value="array"/>
    <server name="QUEUE_CONNECTION" value="sync"/>
    <server name="SESSION_DRIVER" value="array"/>
    <server name="TELESCOPE_ENABLED" value="false"/>
  </php>
</phpunit>
  

Вот фатальная ошибка phpunit. Я не так сильно обеспокоен тем, что мой тестовый пример не выполняется ниже. Основная проблема заключается в неустранимой ошибке «конфигурация не найдена …»

 $ php artisan test
Warning: TTY mode is not supported on Windows platform.


   PASS  TestsUnitExampleTest
  ✓ basic test


   FAIL  TestsUnitappHttpControllersContactControllerTest
  ✕ fail to validate email

  Tests:  1 failed, 1 passed, 1 pending

  Failed asserting that exception of type "ErrorException" matches expected exception "IlluminateValidationValidationException". Message was: "dns_get_record(): DNS Query failed" at D:gitprojsphprubens-gomesvendoreguliasemail-validatorsrcValidationDNSCheckValidation.php:121 D:gitprojsphprubens-gomesvendoreguliasemail-validatorsrcValidationDNSCheckValidation.php:107 D:gitprojsphprubens-gomesvendoreguliasemail-validatorsrcValidationDNSCheckValidation.php:80 D:gitprojsphprubens-gomesvendoreguliasemail-validatorsrcValidationMultipleValidationWithAnd.php:65 D:gitprojsphprubens-gomesvendoreguliasemail-validatorsrcEmailValidator.php:37 D:gitprojsphprubens-gomesvendorlaravelframeworksrcIlluminateValidationConcernsValidatesAttributes.php:666 D:gitprojsphprubens-gomesvendorlaravelframeworksrcIlluminateValidationValidator.php:547 D:gitprojsphprubens-gomesvendorlaravelframeworksrcIlluminateValidationValidator.php:370 D:gitprojsphprubens-gomesvendorlaravelframeworksrcIlluminateValidationValidator.php:401 D:gitprojsphprubens-gomesvendorlaravelframeworksrcIlluminateValidationValidator.php:444 D:gitprojsphprubens-gomesvendorlaravelframeworksrcIlluminateValidationFactory.php:136 D:gitprojsphprubens-gomesvendorlaravelframeworksrcIlluminateFoundationProvidersFoundationServiceProvider.php:58 D:gitprojsphprubens-gomesvendorlaravelframeworksrcIlluminateSupportTraitsMacroable.php:111 D:gitprojsphprubens-gomesappHttpControllersContactController.php:90 D:gitprojsphprubens-gomestestsUnitappHttpControllersContactControllerTest.php:43 .

  at D:gitprojsphprubens-gomesvendorphpunitphpunitsrcFrameworkConstraintConstraint.php:121
    117|         if (!empty($description)) {
    118|             $failureDescription = $description . "n" . $failureDescription;
    119|         }
    120|
  > 121|         throw new ExpectationFailedException(
    122|             $failureDescription,
    123|             $comparisonFailure
    124|         );
    125|     }

  1   D:gitprojsphprubens-gomesvendorphpunitphpunitsrcFrameworkConstraintConstraint.php:55
      PHPUnitFrameworkConstraintConstraint::fail(Object(ErrorException), "")

  2   D:gitprojsphprubens-gomesvendorphpunitphpunitsrcFrameworkAssert.php:2331
      PHPUnitFrameworkConstraintConstraint::evaluate(Object(ErrorException), "")
PHP Fatal error:  Uncaught ReflectionException: Class config does not exist in D:gitprojsphprubens-gomesvendorlaravelframeworksrcIlluminateContainerContainer.php:809
Stack trace:
#0 D:gitprojsphprubens-gomesvendorlaravelframeworksrcIlluminateContainerContainer.php(809): ReflectionClass->__construct('config')
#1 D:gitprojsphprubens-gomesvendorlaravelframeworksrcIlluminateContainerContainer.php(691): IlluminateContainerContainer->build('config')
#2 D:gitprojsphprubens-gomesvendorlaravelframeworksrcIlluminateFoundationApplication.php(796): IlluminateContainerContainer->resolve('config', Array, true)
#3 D:gitprojsphprubens-gomesvendorlaravelframeworksrcIlluminateContainerContainer.php(637): IlluminateFoundationApplication->resolve('config', Array)
#4 D:gitprojsphprubens-gomesvendorlaravelframeworksrcIlluminateFoundationApplication.php(781): IlluminateContainerContainer->make('config', Array)
#5 D:gitprojsphprubens-gomesvendorlaravelframeworksrcIlluminateC in D:gitprojsphprubens-gomesvendorlaravelframeworksrcIlluminateContainerContainer.php on line 811
PHP Stack trace:
PHP   1. {main}() D:gitprojsphprubens-gomesvendorphpunitphpunitphpunit:0
PHP   2. PHPUnitTextUICommand::main($exit = *uninitialized*) D:gitprojsphprubens-gomesvendorphpunitphpunitphpunit:61
PHP   3. PHPUnitTextUICommand->run($argv = *uninitialized*, $exit = *uninitialized*) D:gitprojsphprubens-gomesvendorphpunitphpunitsrcTextUICommand.php:100
PHP   4. PHPUnitTextUITestRunner->run($suite = *uninitialized*, $arguments = *uninitialized*, $warnings = *uninitialized*, $exit = *uninitialized*) D:gitprojsphprubens-gomesvendorphpunitphpunitsrcTextUICommand.php:147
PHP   5. PHPUnitFrameworkTestSuite->run($result = *uninitialized*) D:gitprojsphprubens-gomesvendorphpunitphpunitsrcTextUITestRunner.php:671
PHP   6. PHPUnitFrameworkTestSuite->run($result = *uninitialized*) D:gitprojsphprubens-gomesvendorphpunitphpunitsrcFrameworkTestSuite.php:665
PHP   7. PHPUnitFrameworkTestSuite->run($result = *uninitialized*) D:gitprojsphprubens-gomesvendorphpunitphpunitsrcFrameworkTestSuite.php:665
PHP   8. TestsUnitappHttpControllersContactControllerTest->run($result = *uninitialized*) D:gitprojsphprubens-gomesvendorphpunitphpunitsrcFrameworkTestSuite.php:665
PHP   9. PHPUnitFrameworkTestResult->run($test = *uninitialized*) D:gitprojsphprubens-gomesvendorphpunitphpunitsrcFrameworkTestCase.php:880
PHP  10. PHPUnitFrameworkTestResult->addFailure($test = *uninitialized*, $e = *uninitialized*, $time = *uninitialized*) D:gitprojsphprubens-gomesvendorphpunitphpunitsrcFrameworkTestResult.php:894
PHP  11. NunoMaduroCollisionAdaptersPhpunitPrinter->addFailure($testCase = *uninitialized*, $error = *uninitialized*, $time = *uninitialized*) D:gitprojsphprubens-gomesvendorphpunitphpunitsrcFrameworkTestResult.php:391
PHP  12. NunoMaduroCollisionAdaptersPhpunitStyle->writeError($state = *uninitialized*, $throwable = *uninitialized*) D:gitprojsphprubens-gomesvendornunomadurocollisionsrcAdaptersPhpunitPrinterContents.php:114
  

Below is controller being tested. Noticed that this is very basic code and testing just to see if things work.

And BTW I am learning Laravel.

 $ cat app/Http/Controllers/ContactController.php
<?php
namespace AppHttpControllers;

use IlluminateHttpRequest;
use IlluminateSupportMessageBag;
use IlluminateSupportFacadesLog;
use ReCaptchaReCaptcha;

/**
 * Controller to handle incoming "/contact" form requests.
 *
 * @author Rubens Gomes <rubens.s.gomes@gmail.com>
 * @copyright 2020 Rubens Gomes
 */
final class ContactController extends Controller
{

    /** @var array containing fields to be used on the view.*/
    private $data;

    /** @var array contact form validation rules. */
    private $formRules;

    /**
     *
     * @var ReCaptchaReCaptcha instance of Google ReCaptcha to be injected
     *      during unit testing. If no instance is injected a new one is created.
     */
    private $recaptcha;

    /**
     * The default constructor.
     *
     * @param ReCaptcha $rc The Google ReCaptcha object.
     */
    public function __construct(ReCaptcha $rc = null)
    {
        if ($rc === null) {
            $this->recaptcha = new ReCaptcha(config('services.recaptcha.secret_key'));
        } else {
            $this->recaptcha = $rc;
        }

        $this->data = [
            'pageId' => 'contact',
            'homeHref' => '/#home',
            'aboutHref' => '/#about',
            'contactHref' => '#contact'
        ];

        $this->formRules = [
            'email' => 'required|email:dns',
            'name' => 'required',
            'msg' => 'required',
            'g-recaptcha-response' => 'required'
        ];
        Log::debug(__CLASS__ . " constructed");
    }

    public function __destruct()
    {
        Log::debug(__CLASS__ . " destructed");
    }

    /**
     * Process the incoming GET request to render the contact page.
     *
     * @return IlluminateViewView The contact main page view.
     */
    public function index()
    {
        Log::debug(__CLASS__ . ":" . __FUNCTION__);
        return view('contact', $this->data);
    }

    /**
     * Handles the contact message form POST submit by validating the form
     * fields, validating the captcha and then sending an email message with
     * the information provided in the form.
     *
     * @param IlluminateHttpRequest $request
     *            The HTTP request
     * @return IlluminateViewView The contact main page view.
     */
    public function sendmsg(Request $request)
    {
        Log::debug(__CLASS__ . ":" . __FUNCTION__);
        // validate input contact fields
        Log::debug('validating contact form');
        $request->validate($this->formRules);

        // validate the captcha
        $captcha = $request->input(config('services.recaptcha.resp_parm'));
        Log::debug('validating captcha...');
        $response = $this->recaptcha->verify($captcha);

        if (! $response->isSuccess()) {
            Log::warning('failed to authenticate captcha');
            $captchaError = new MessageBag();
            $captchaError->add('recaptcha_error', 'Failed to authenticate captcha');
            return view('contact', $this->data)->withErrors($captchaError);
        }

        return redirect()->back()->withSuccess('Your message has been successfully submitted.');
    }
}
/******************************************************************************/

// EOF
  

And here is my controller test code:

 $ cat tests/Unit/app/Http/Controllers/ContactControllerTest.php
<?php
namespace TestsUnitappHttpControllers;

use AppHttpControllersContactController;
use IlluminateHttpRequest;
use IlluminateValidationValidationException;
use TestsTestCase;
use ReCaptchaReCaptcha;

class ContactControllerTest extends TestCase
{

    /** @var AppHttpControllersContactController The controller being tested */
    private $controller;

    /** @var ReCaptchaReCaptcha The Google ReCaptcha being doubled */
    private $rcStub;

    public function setUp(): void
    {
        parent::setUp();
        $this->rcStub = $this->createStub(ReCaptcha::class);
        $this->controller = new ContactController($this->rcStub);
    }

    public function tearDown(): void
    {
        parent::tearDown();
    }

    public function testFailToValidateEmail()
    {
        $this->expectException(ValidationException::class);

        $form = [
            'email' => 'rubens.s.gomes @ gmail.com',
            'msg' => 'This is a test.nRubens Gomes',
            'name' => 'Rubens Gomes',
            'g-recaptcha-response' => 'hello google captcha'
        ];

        $request = Request::create('/contact/sendmsg', 'POST', $form);
        $this->controller->sendmsg($request);
    }
}

  

Вот мой файл .env:

 $ cat .env
APP_NAME="Laravel"
APP_ENV="local"
APP_KEY="base64:mJmYLlc2V43AKfa3u7s1po7RHyPDajRZIB4pIArTyjg="
APP_DEBUG=true
APP_URL="http://localhost"

LOG_CHANNEL="stack"

DB_CONNECTION="mysql"
DB_HOST="127.0.0.1"
DB_PORT=3306
DB_DATABASE="laravel"
DB_USERNAME="root"
DB_PASSWORD="root"

BROADCAST_DRIVER="log"
CACHE_DRIVER="file"
QUEUE_CONNECTION="sync"
SESSION_DRIVER="file"
SESSION_LIFETIME=120

REDIS_HOST="127.0.0.1"
REDIS_PASSWORD="null"
REDIS_PORT=6379

MAIL_MAILER="smtp"
MAIL_HOST="smtp.mailtrap.io"
MAIL_PORT=2525
MAIL_USERNAME="null"
MAIL_PASSWORD="null"
MAIL_ENCRYPTION="null"
MAIL_FROM_ADDRESS="null"
MAIL_FROM_NAME="${APP_NAME}"

AWS_ACCESS_KEY_ID=""
AWS_SECRET_ACCESS_KEY=""
AWS_DEFAULT_REGION="us-east-1"
AWS_BUCKET=""

PUSHER_APP_ID=""
PUSHER_APP_KEY=""
PUSHER_APP_SECRET=""
PUSHER_APP_CLUSTER="mt1"

MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

RECAPTCHA_DOMAIN="NOT_DISPLAYED"
RECAPTCHA_SITE_KEY="NOT_DISPLAYED"
RECAPTCHA_SECRET_KEY="NOT_DISPLAYED"
RECAPTCHA_OWNER="rubens.s.gomes@gmail.com"
RECAPTCHA_VERSION="V2"
  

Комментарии:

1. Не могли бы вы поделиться своим контроллером и тестовым кодом контроллера?

2. Вы можете найти множество идей здесь

3. Я попробовал предложение «php artisan config: cache» в одном из сообщений на github. Я увидел улучшение (на одну трассировку стека меньше) в phpunit. Но все еще есть один случай «PHP Fatal error: Uncaught ReflectionException: конфигурация класса не существует в …». Я обновил свой первоначальный пост последней информацией 27.08.2020.

Ответ №1:

Я переписал весь приведенный выше код. И теперь он работает нормально. Ниже приведены фрагменты некоторого нового кода.

composer.json:

 $ cat composer.json
{
        "name" : "rubens-gomes/rubens-gomes.com",
        "type" : "project",
        "description" : "rubens-gomes.com Web Site",
        "homepage" : "https://rubens-gomes.com",
        "keywords" : [
                "framework",
                "laravel"
        ],
        "license" : "PROPRIETARY",
        "authors" : [{
                        "name" : "Rubens Gomes",
                        "email" : "rubens.s.gomes@gmail.com",
                        "homepage" : "https://rubens-gomes.com",
                        "role" : "Developer"
                }
        ],
        "support" : {
                "email" : "rubens.s.gomes@gmail.com"
        },
        "require" : {
                "php" : ">=7.4",
                "fideloper/proxy" : "^4.2",
                "fruitcake/laravel-cors" : "^2.0",
                "google/recaptcha" : "^1.2",
                "guzzlehttp/guzzle" : "^6.3",
                "laravel/framework" : "^7.24",
                "laravel/tinker" : "^2.0"
        },
        "require-dev" : {
                "facade/ignition" : "^2.0",
                "fzaninotto/faker" : "^1.9.1",
                "mockery/mockery" : "^1.3.1",
                "nunomaduro/collision" : "^4.1",
        "phpunit/phpunit" : "^8.5"
        },
        "config" : {
                "optimize-autoloader" : true,
                "preferred-install" : "dist",
                "sort-packages" : true
        },
        "extra" : {
                "laravel" : {}
        },
        "autoload" : {
                "psr-4" : {
                        "App\" : "app/"
                },
                "classmap" : [
                        "database/seeds",
                        "database/factories"
                ]
        },
        "autoload-dev" : {
                "psr-4" : {
                        "Tests\" : "tests/"
                }
        },
        "minimum-stability" : "dev",
        "prefer-stable" : true,
        "scripts" : {
                "post-autoload-dump" : [
                        "Illuminate\Foundation\ComposerScripts::postAutoloadDump",
                        "@php artisan package:discover --ansi"
                ],
                "post-root-package-install" : "@php -r "file_exists('.env') || copy('.env.example', '.env');"",
                "post-create-project-cmd" : "@php artisan key:generate --ansi",
                "post-update-cmd" : "@composer dump-autoload"
        }
}
  

phpunit.xml:

 $ cat phpunit.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
  To run the unit tests configured in this PHPUnit XML configuration file:

       php artisan test -vvv

   @author Rubens Gomes <rubens.s.gomes@gmail.com>
   @link https://rubens-gomes.com
-->
<phpunit
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
  bootstrap="bootstrap/app.php"
  colors="true"
  verbose="true">
  <testsuites>
    <testsuite name="Unit">
      <directory suffix="Test.php">./tests/Unit</directory>
    </testsuite>
    <testsuite name="Feature">
      <directory suffix="Test.php">./tests/Feature</directory>
    </testsuite>
  </testsuites>
  <php>
    <server name="APP_ENV" value="testing"/>
  </php>
</phpunit>
  

.env:

 $ cat .env
APP_NAME="rubens-gomes.com"
APP_ENV="testing"
APP_KEY="base64:mJmYLlc2V43AKfa3u7s1po7RHyPDajRZIB4pIArTyjg="
APP_DEBUG=true
APP_URL="http://localhost:8080"

LOG_CHANNEL="stdout"

MAIL_MAILER="smtp"
MAIL_HOST="smtp.gmail.com"
MAIL_PORT=465
MAIL_USERNAME="NOT_DISPLAYED"
MAIL_PASSWORD="NOT_DISPLAYED"
MAIL_FROM_ADDRESS="NOT_DISPLAYED"
MAIL_FROM_NAME="${APP_NAME}"

RECAPTCHA_DOMAIN="rubens-gomes.com"
RECAPTCHA_SITE_KEY="NOD_DISPLAYED"
RECAPTCHA_SECRET_KEY="NOT_DISPLAYED"
RECAPTCHA_OWNER="rubens.s.gomes@gmail.com"
RECAPTCHA_VERSION="V2"
  

тестовый вывод:

 $ php artisan test -vvv
Warning: TTY mode is not supported on Windows platform.


   PASS  TestsUnitExampleTest
  ✓ basic test




   RUNS  TestsUnitappHttpControllersContactControllerTest
  • fail due to invalid form

  Tests:  4 passed, 17 pending
[2020-08-30T05:29:18.173039 00:00] testing.DEBUG: creating contact instance [] []

   RUNS  TestsUnitappHttpControllersContactControllerTest
  • ensure sucess response for valid form


   PASS  TestsUnitappHttpControllersContactControllerTest
  ✓ ensure request to index page works
  ✓ fails due to wrong resource
  ✓ fail due to post method not allowed for index page
  ✓ fail due to invalid form
  ✓ ensure sucess response for valid form



   PASS  TestsUnitappHttpControllersHomeControllerTest
  ✓ ensure request to index page works
  ✓ fails due to wrong resource




   PASS  TestsUnitappMailContactRequestMailableTest
  ✓ fail due to null contact
  ✓ ensure constructor works
  ✓ ensure build works




   PASS  TestsUnitappMailContactResponseMailableTest
  ✓ fail due to null contact
  ✓ ensure constructor works
  ✓ ensure build works

   RUNS  TestsUnitappModelContactTest
  • fail due to invalid email

   RUNS  TestsUnitappModelContactTest
  • fail due to invalid email domain





   PASS  TestsUnitappModelContactTest
  ✓ fail due to invalid email
  ✓ fail due to invalid email domain
  ✓ ensure contact is created
  ✓ ensure email is not empty
  ✓ ensure name is not empty
  ✓ ensure msg is not empty


   PASS  TestsFeatureExampleTest
  ✓ basic test

  Tests:  21 passed
  Time:   4.93s
  

ContactControllerTest.php:

 <?php
namespace TestsUnitappHttpControllers;

use AppHttpControllersContactController;
use AppMailContactRequestMailable;
use IlluminateHttpRequest;
use IlluminateSupportFacadesMail;
use ReCaptchaReCaptcha;
use TestsTestCase;

class ContactControllerTest extends TestCase
{

    /** @var AppHttpControllersContactController The controller being tested */
    private $controller;

    /** @var ReCaptchaReCaptcha The Google ReCaptcha being doubled */
    private $rcStub;

    /** @var array valid post form data for testing purposes */
    private const VALID_FORM = [
        'email' => 'rubens.s.gomes@gmail.com',
        'msg' => 'This is a test.nRubens Gomes',
        'name' => 'Rubens Gomes',
        'g-recaptcha-response' => 'hello google captcha'
    ];

    /** @var array invalid post form data for testing purposes */
    private const INVALID_FORM = [
        'email' => 'rubens.s.gomes@gmail.com',
        'msg' => 'This is a test.nRubens Gomes',
        'name' => '',
        'g-recaptcha-response' => 'hello google captcha'
    ];

    public function setUp(): void
    {
        parent::setUp();
        $this->rcStub = $this->createStub(ReCaptcha::class);
        $this->controller = new ContactController($this->rcStub, Mail::fake());
    }

    public function tearDown(): void
    {
        parent::tearDown();
    }

    public function testEnsureRequestToIndexPageWorks()
    {
        $response = $this->get('/contact/');
        $this->assertTrue($response->isOk());
    }

    public function testFailsDueToWrongResource()
    {
        $response = $this->get('/contact/hello');
        $response->assertStatus(404);
    }

    public function testFailDueToPostMethodNotAllowedForIndexPage()
    {
        $response = $this->post('/contact/');
        $response->assertStatus(405);
    }

    public function testFailDueToInvalidForm()
    {
        $response = $this->post('/contact/sendmsg', self::INVALID_FORM);
        $response->assertRedirect();
    }

    // unit testing controller
    public function testEnsureSucessResponseForValidForm()
    {
        $request = Request::create('/contact/sendmsg', 'POST', self::VALID_FORM);
        $rcResp = new ReCaptchaResponse(TRUE);
        $this->rcStub->method('verify')->willReturn($rcResp);
        $this->controller->sendmsg($request);
        Mail::assertSent(ContactRequestMailable::class, 1);
    }
}
  

ContactController.php

 <?php
namespace AppHttpControllers;

use AppMailContactRequestMailable;
use AppModelContact;
use IlluminateHttpRequest;
use IlluminateSupportMessageBag;
use IlluminateSupportFacadesLog;
use IlluminateSupportFacadesMail;
use ReCaptchaReCaptcha;

/**
 * Controller to handle incoming "/contact" form requests.
 *
 * @author Rubens Gomes <rubens.s.gomes@gmail.com>
 */
final class ContactController extends Controller
{

    /** @var array containing fields to be used in the view.*/
    private const VIEW_DATA = [
        'pageId' => 'contact',
        'homeHref' => '/#home',
        'aboutHref' => '/#about',
        'contactHref' => '#contact'
    ];

    /** @var IlluminateSupportFacadesMail instance of mail service. */
    private $mailer;

    /** @var ReCaptchaReCaptcha instance of Google ReCaptcha. */
    private $recaptcha;

    /**
     * The default constructor.
     *
     * @param ReCaptcha $rc
     *            The Google ReCaptcha object.
     */
    public function __construct(ReCaptcha $rc = null)
    {
        if ($rc === null) {
            $this->recaptcha = new ReCaptcha(config('services.recaptcha.secret_key'));
        } else {
            // used during unit testing to inject a test double object
            $this->recaptcha = $rc;
        }
    }

    /**
     * Process the incoming GET request to render the contact page.
     *
     * @return IlluminateViewView The contact main page view.
     */
    public function index()
    {
        return view('contact', self::VIEW_DATA);
    }

    /**
     * Handles the contact message form POST submit by validating the form
     * fields, validating the captcha and then sending an email message with
     * the information provided in the form.
     *
     * @param IlluminateHttpRequest $request
     *            The HTTP request
     * @return IlluminateViewView The contact main page view.
     */
    public function sendmsg(Request $request)
    {
        // validate and create contact
        $data = [
            'name' => $request->input('name'),
            'email' => $request->input('email'),
            'msg' => $request->input('msg')
        ];

        $contact = null;

        try {
            Log::debug('creating contact instance');
            $contact = new Contact($data['name'], $data['email'], $data['msg']);
        } catch (InvalidArgumentException $ex) {
            Log::error('failed to create contact', $data);
            return redirect()->back()
                ->withException($ex)
                ->withErrors($ex->getMessage());
        }

        // validate the captcha
        $captcha = $request->input(config('services.recaptcha.resp_parm'));
        Log::debug('validating captcha', ['captcha' => $captcha]);
        $response = $this->recaptcha->verify($captcha);

        if (! $response->isSuccess()) {
            Log::warning('failed to authenticate captcha', ['captcha' => $captcha]);
            $captchaError = new MessageBag();
            $captchaError->add('recaptcha_error', 'Failed to authenticate captcha');
            return redirect()->back()->withErrors($captchaError);
        }

        // send message by email
        Log::debug('sending email', ['email' => $contact->getEmail() ]);
        $reqMail = new ContactRequestMailable($contact);
        Mail::to($contact->getEmail())->send($reqMail);
        return redirect()->back()->withSuccess('Your message has been successfully submitted.');
    }
}
/******************************************************************************/

// EOF

  

Contact.php :

 <?php
namespace AppModel;

use IlluminateSupportFacadesLog;
use IlluminateSupportFacadesValidator;

/**
 * A data model object to represent a contact (e.g., from the contact form).
 *
 * @author Rubens Gomes <rubens.s.gomes@gmail.com>
 */
class Contact
{

    /** @var array $validationRules The rules for validating input data */
    private static $validationRules = [
        'name' => 'required|max:100',
        'email' => 'required|email:rfc,dns',
        'msg' => 'required|max:1000',
    ];

    /** @var string $name The contact name */
    private $name;

    /** @var string $email The contact email address */
    private $email;

    /** @var string $msg The contact message */
    private $msg;

    /**
     * Default constructor.
     *
     * @param string $name
     *            The non-blank contact name.
     * @param string $email
     *            The non-blank contact email.
     * @param string $msg
     *            The non-blank contact message.
     * @throws InvalidArgumentException if any of the arguments is not valid.
     */
    public function __construct($name, $email, $msg)
    {
        $data = [
            'name' => $name,
            'email' => $email,
            'msg' => $msg
        ];

        $validator = Validator::make($data, self::$validationRules);

        if($validator->fails()) {
            Log::error("name or email invalid", $data);
            throw new InvalidArgumentException("Invalid argument: " . $validator->errors());
        }

        $this->name = $name;
        $this->email = $email;
        $this->msg = $msg;
    }

    public function getEmail() : string
    {
        return $this->email;
    }

    public function getMessage() : string
    {
        return $this->msg;
    }

    public function getName() : string
    {
        return $this->name;
    }

}
/******************************************************************************/

// EOF
  

ContactRequestMailable.php:

 <?php
namespace AppMail;

use AppModelContact;
use IlluminateMailMailable;

/**
 * Mailable used to send email of message in contact form.
 *
 * @author Rubens Gomes
 */
class ContactRequestMailable extends Mailable
{

    private const SUBJECT = "Rubens Gomes - Contact";

    /** @var Contact The contact instance. */
    private $contact;

    /**
     * Default constructor
     *
     * @param Contact $contact
     *            the non-null and valid contact instance.
     * @throws InvalidArgumentException if any of the arguments is not valid.
     */
    public function __construct($contact = null)
    {
        if (is_null($contact)) {
            throw new InvalidArgumentException("contact cannot be null.");
        }

        $this->contact = $contact;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->subject(self::SUBJECT)
            ->locale('en')
            ->from(config('mail.from.address'), config('mail.from.name'))
            ->to(config('mail.from.address'), config('mail.from.name'))
            ->view('emails.contact-request')
            ->with([
            'name' => $this->contact->getName(),
            'email' => $this->contact->getEmail(),
            'msg' => $this->contact->getMessage()
        ]);
    }
}
/******************************************************************************/

// EOF```
  

Ответ №2:

У меня эта проблема в тестах @depens. Я очистил удаление, чтобы исправить это.

 protected function tearDown() :void
{
    // Don't clear test environment between tests
}