Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.6k
Description
Symfony version(s) affected
7.0.*
Description
I'm following the official documentation regarding tests and DTOs but I get this error when running the test. The code itself works, I've tried the API with Postman. But the test seemingly has a problem to map the request to the DTO for some reason. The error I get is this:
1) App\Tests\Feature\SignUp\Application\Http\Controller\Api\SignUpControllerTest::testSuccessfulSignUpSymfony\Component\DependencyInjection\Exception\RuntimeException: Cannot autowire service "App\Feature\SignUp\Application\Transfer\ProfileTransfer": argument "$firstName" of method "__construct()" is type-hinted "string", you should configure its value explicitly.
The DTO looks like they are describedin the documentation and the controller works, but the test has trouble. They arenested DTOs, I have a SignUpTransfer that then is using an UserTransfer and a ProfileTransfer.
SignUpTransfer|--UserTransfer |--ProfileTransfer
And use it in the controller#[MapRequestPayload] SignUpTransfer $signUpTransfer
:
#[Route( path:'/api/sign-up', name:'api_sign_up', methods: ['POST'] )]publicfunctionsignUp( #[MapRequestPayload]SignUpTransfer$signUpTransfer ):JsonResponse|ErrorResponse {//... }
ProfileTransfer:
<?phpdeclare(strict_types=1);namespaceApp\Feature\SignUp\Application\Transfer;useSymfony\Component\Validator\ConstraintsasAssert;readonlyclass ProfileTransfer{publicfunction__construct( #[Assert\NotBlank()] #[Assert\Length(min:2, max:64)]publicstring$firstName, #[Assert\NotBlank()] #[Assert\Length(min:2, max:64)]publicstring$lastName ) { }publicfunctiongetFirstName():string {return$this->firstName; }publicfunctiongetLastName():string {return$this->lastName; }}
SignUpTransfer
<?phpdeclare(strict_types=1);namespaceApp\Feature\SignUp\Application\Transfer;useSymfony\Component\Validator\ConstraintsasAssert;readonlyclass SignUpTransfer{publicfunction__construct( #[Assert\NotNull()] #[Assert\Valid()]publicUserTransfer$user, #[Assert\NotNull()] #[Assert\Valid()]publicProfileTransfer$profile ) { }publicfunctiongetUser():UserTransfer {return$this->user; }publicfunctiongetProfile():ProfileTransfer {return$this->profile; }}
The test code
<?phpdeclare(strict_types=1);namespaceApp\Tests\Feature\SignUp\Application\Http\Controller\Api;usePsr\Http\Message\MessageInterface;usePsr\Http\Message\ServerRequestInterface;useSymfony\Bundle\FrameworkBundle\Test\WebTestCase;class SignUpControllerTestextends WebTestCase{protectedfunctionapiRequest(string$url,string$method,$data,$parameters = [],$files = []) {returnstatic::createClient()->request( method:$method, uri:$url, parameters:$parameters, files:$files, server: ['HTTP_ACCEPT' =>'application/json','CONTENT_TYPE' =>'application/json' ], content:json_encode($data,JSON_THROW_ON_ERROR), changeHistory:true ); }publicfunctiontestSuccessfulSignUp():void {$this->apiRequest('/sign-up','POST', ['user' => ['email' =>'testmail@test.local','password' =>'password','confirmPassword' =>'password' ],'profile' => ['firstName' =>'John','lastName' =>'Doe' ] ]);self::assertResponseStatusCodeSame(201);self::assertResponseHeaderSame('Content-Type','application/json'); }}
The code works, the problem is the test. I can call the endpoint via Postman without problems:
How to reproduce
Created a DTO with child DTOs like this structure:
SignUpTransfer|--UserTransfer |--ProfileTransfer
And try to call the API endpoint with the test client.
<?phpdeclare(strict_types=1);namespace App\Tests\Feature\SignUp\Application\Http\Controller\Api;use Psr\Http\Message\MessageInterface;use Psr\Http\Message\ServerRequestInterface;use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;class SignUpControllerTest extends WebTestCase{ protected function apiRequest(string $url, string $method, $data, $parameters = [], $files = []) { return static::createClient()->request( method: $method, uri: $url, parameters: $parameters, files: $files, server: [ 'HTTP_ACCEPT' => 'application/json', 'CONTENT_TYPE' => 'application/json' ], content: json_encode($data, JSON_THROW_ON_ERROR), changeHistory: true ); } public function testSuccessfulSignUp(): void { $this->apiRequest('/sign-up', 'POST', [ 'user' => [ 'email' => 'testmail@test.local', 'password' => 'password', 'confirmPassword' => 'password' ], 'profile' => [ 'firstName' => 'John', 'lastName' => 'Doe' ] ]); self::assertResponseStatusCodeSame(201); self::assertResponseHeaderSame('Content-Type', 'application/json'); }}
Possible Solution
I have not yet investigated it but there must be a difference to how the real request is handled and the one from the test client.
Additional Context
No response