saloonphp / saloon

🤠 Build beautiful API integrations and SDKs with Saloon
https://docs.saloon.dev
MIT License
2.03k stars 105 forks source link

Possible to Use Multiple Instances of Same Request in Single Test? #428

Closed chrismcintosh closed 3 weeks ago

chrismcintosh commented 2 months ago

I'm sure there are much smarter ways to go about what I'm trying to do. I've reviewed the documentation and I can't find what I need.

        MockClient::global([
           // ❌ DOES NOT GET USED
           NetworkCreatePrivateRequest::class => MockResponse::fixture(
                "create_private_network_request"
            ),
            // ✅ GETS USED FOR BOTH NETWORK CREATE
            NetworkCreatePrivateRequest::class => MockResponse::fixture(
                "create_vm_network_request"
            ),
           // ❌ DOES NOT GET USED
            CreateServer::class => MockResponse::fixture(
                "create_server_1"
            ),
           // ❌ DOES NOT GET USED
            CreateServer::class => MockResponse::fixture(
                "create_server_2"
            ),
           // ✅ GETS USED FOR ALL 3 CREATE SERVER
            CreateServer::class => MockResponse::fixture(
                "create_server_3"
            ),
        ]);

I have a test where I use the same request classes multiple times. Each time the request class is used it needs to respond with data from a different fixture to mimic what the code is doing.

I assumed the MockClient would use the first instance of a request class encountered and after it is used once it looks for the next instance in the MockClient but that is not how it works.

The problem I am running into is that it seems that only the last instances in the MockClient::global array are used.

Is it possible to tailor these calls in order with responses to have different fixtures/data - or is there another way to achieve this?

I would like to avoid create a separate class for each possible instance of network or server because the requests are so similar - but the responses need to be different.

Best, Chris

craigpotter commented 1 month ago

There are multiple ways to do it.

In your test, call the MockClient again

 MockClient::global([
           NetworkCreatePrivateRequest::class => MockResponse::fixture(
                "create_private_network_request"
            ),
            CreateServer::class => MockResponse::fixture(
                "create_server_1"
            ),
        ]);

// Do first load of tests to trigger requests 

 MockClient::global([
            NetworkCreatePrivateRequest::class => MockResponse::fixture(
                "create_vm_network_request"
            ),
            CreateServer::class => MockResponse::fixture(
                "create_server_2"
            ),
        ]);

// Do next load of tests to trigger next set of requests 

Depending on your code, you could also pass a closure to the mock.

 MockClient::global([

           NetworkCreatePrivateRequest::class => function (PendingRequest $pendingRequest) {
               $request = $pendingRequest->getRequest(); // This will get the underlying instance of NetworkCreatePrivateRequest 

               $networkName = $request->name; // assuming you have a name property on your request but you could get it from the body or anything else you pass in. 

               return MockResponse::fixture("create_{ $networkName }_network_request");

            },
]);
chrismcintosh commented 3 weeks ago

@craigpotter I used the second recommendation you made and it worked perfectly. Thanks so much for your help!

This kind of thing works well

 MockClient::global([

           NetworkCreatePrivateRequest::class => function (PendingRequest $pendingRequest) {
               $request = $pendingRequest->getRequest(); // This will get the underlying instance of NetworkCreatePrivateRequest 

               $networkName = $request->name; // assuming you have a name property on your request but you could get it from the body or anything else you pass in. 

               return MockResponse::fixture("create_{ $networkName }_network_request");

            },
]);
craigpotter commented 3 weeks ago

Glad I could help 😌 ☺️