Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No way to pass mocked SoapClient in tests #45

Open
vadimonus opened this issue May 25, 2022 · 5 comments
Open

No way to pass mocked SoapClient in tests #45

vadimonus opened this issue May 25, 2022 · 5 comments
Assignees

Comments

@vadimonus
Copy link

Trying to write tests for next case. My app is calling soap service and correctly stores response to db. I have many response xml examples from service documentation app, so I use Mockery::mock(\SoapClient::class) to make partial mock and override __doRequest method to return expected xml.
But after that i have no way to pass this class to AbstractSoapClientBase descendant. What i see:

  1. Default soap client is defined by constant in SoapClientInterface, so it is not possible to use class, created by mockery, or any anonimous class.
  2. AbstractSoapClientBase::initSoapClient, called by constructor, allways creates default SoapClient, because getSoapClientClassName() is called without params. There is no way to pass $soapClientClassName with options.
  3. If use setSoapClient() to set other implementation of soap client, SoapClient is created two times, first in initSoapClient, second is Mock.
  4. It is possible to override AbstractSoapClientBase::getSoapClientClassName class in tests, but then i need some sort of injection to pass overrided class to application instead of original only in tests. It would be much simplier to do so with configs.
@mikaelcom
Copy link
Member

mikaelcom commented May 25, 2022

Can you paste your testing code? Or create a Gist containing the files

@mikaelcom mikaelcom self-assigned this May 25, 2022
@vadimonus
Copy link
Author

Currently i use Laravel container to Mock Serivce

In application

$options = array(
    AbstractSoapClientBase::WSDL_URL => 'https://xxxx?wsdl',
    AbstractSoapClientBase::WSDL_CLASSMAP => ClassMap::get(),
);
$service = app()->make(new Service($options));
$service->setSoapHeaderHeader($header);
if ($send->sendToESP(new ServiceRequest()) !== false) {
    print_r($send->getResult());
} else {
    print_r($send->getLastError());
}

in test

    protected function mockApi($xml): void
    {
        $this->app->bind(Service::class, function ($app, $params) use ($xml) {
            [$options] = $params;
            $soapClientMock = Mockery::mock(SoapClient::class, [
                $options[AbstractSoapClientBase::WSDL_URL],
                [
                    'classmap' => $options[AbstractSoapClientBase::WSDL_CLASSMAP],
                ],
            ]);
            $soapClientMock->makePartial();
            $soapClientMock->shouldReceive('__doRequest')->andReturn($xml);
            $soapClientMock->shouldReceive('__getLastResponse')->andReturn($xml);

            $serviceMock = new Service();
            $serviceMock->setSoapClient($soapClientMock);
            return $serviceMock;
        });
    }

But as you can see, it's very complicated solution.

@mikaelcom
Copy link
Member

I currently don't see a solution to solve your issue. It's working this way and modifying it would myabe break the usage long ago designed as it is.
Feel free to propose a way to ease your issue.

@vadimonus
Copy link
Author

One of improvement that i currently can see, is to add config option for class name, and pass this option to getSoapClientClassName in initSoapClient, because currently there is no other way to pass any value to getSoapClientClassName

@mikaelcom
Copy link
Member

Maybe I'm wrong but imagine you:

  • create your own SoapClient class
  • create your own SoapClientBase class from which the ServiceType class would inherit
  • use SoapClientBase as the main class using the --soapclient option when generating the package (if you're actually using the https://github.com/WsdlToPhp/PackageGenerator project)
  • mock the SoapClient class in your test or change its behaviour depending on the current "env" context (prod, dev, test)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants