将mock的返回值返回给phpunit中的主程序

问题描述 投票:0回答:1

好的,这是上下文。我在 Laravel 工作,我正在尝试编写一个单元测试来验证事务“关闭”时发生的一些计算。我将跳过这方面的细节,但一旦过了一定时间,我们会将付款汇总到一笔交易中(因此,如果一个人购买了 5 美元,然后是 3 美元,然后是 6 美元,我们将电汇给她 14 美元,而不是三个单独的交易)量)。

现在,我们有一个非常特殊的计算,我们试图在聚合时将其落实到位,这就是我正在尝试测试的。由于需要大约 10 个步骤来重现计算启动的必要条件,因此编写单元测试似乎是最合乎逻辑的路径。

除了一件事之外,一切正常。在设置计算所需的各个步骤中,我们正在调用外部平台......如果可能的话,我想避免这种情况。也就是说,因为我真的不需要这样做,因为我可以轻松地模拟它们返回的内容,而且......这是一个单元测试,如果我可以帮助它,我不希望它受到外界的突发奇想,哈哈.

无论如何,这是主程序的一部分:

public function purchase(Cart $cart, Card $card)
{
    // lots of treatment

    // this is the call to the external platform
    $monerisGateway = app()->make(mpgHttpsPost::class, [ 
        'storeid' => $this->storeId,
        'apitoken' => $this->apiKey,
    ]);

    $monerisResponse = $monerisGateway->getMonerisResponse();

    log::debug($monerisResponse->getAuthCode());
    log::debug($monerisResponse->getReferenceNum());

    // Lots of treatment after
}

然后在我的单元测试中,我有这个:

private function myMonerisResponse()
{
    $e = new \Exception();
    log::debug("myMonerisResponse");
    log::debug($e->getTraceAsString());
    $receiptId = 'T'.mb_substr(bin2hex(random_bytes(10)), 0, 13).'-'.random_int(100, 999);
    $referenceNumber = random_int(100000, 999999).random_int(100000, 999999).random_int(100000, 999999);

    $authCode = 'KN'.random_int(1000, 9999);
    $dateTime = Carbon::now()->format('Y-m-d');
    $time = Carbon::now()->format('H:i:s');
    // $transAmount = $transAmount;
    $transId = random_int(100000, 999999).'-0_'.random_int(100, 999);
    $msgId = '1F'.random_int(1000, 9999).random_int(1000, 9999).random_int(10000, 99999);

    $this->mpgXmlString = '
    <?xml version="1.0" standalone="yes"?>
        <response>
            <receipt>
                <ReceiptId>T65f9dae711fb5-319</ReceiptId>
                <ReferenceNum>660053720012340910</ReferenceNum>
                <ResponseCode>027</ResponseCode>
                <ISO>01</ISO>
                <AuthCode>KN6128</AuthCode>
                <TransTime>14:35:20</TransTime>
                <TransDate>2024-03-19</TransDate>
                <TransType>01</TransType>
                <Complete>true</Complete>
                <Message>APPROVED           *                    =</Message>
                <TransAmount>10.31</TransAmount>
                <CardType>M</CardType>
                <TransID>277630-0_718</TransID>
                <TimedOut>false</TimedOut>
                <BankTotals>null</BankTotals>
                <Ticket>null</Ticket>
                <CorporateCard>false</CorporateCard>
                <MessageId>1F4079525206486</MessageId>
                <AvsResultCode>R</AvsResultCode>
                <ITDResponse>null</ITDResponse>
                <CvdResultCode>1P</CvdResultCode>
                <IsVisaDebit>false</IsVisaDebit>
            </receipt>
        </response>';

    return new mpgResponse($this->mpgXmlString);
}

/**
 * @test
 */
public function testTotalWithoutCancellationOverMaxContribution()
{

    $this->mockInstance(mpgHttpsPost::class, function ($mock) {
        $mock->shouldReceive('getMonerisResponse')
            ->once()
            ->andReturn($this->myMonerisResponse());
    }, true, true);

    
}

所以基本上,我想做的是让主程序使用我的模拟方法而不是调用 Moneris 网关。到目前为止,我可以确认该方法本身被调用,因为里面的

log::debug()
显示在 laravel.log 文件中。我的问题是主程序永远得不到返回值。

无论如何,是否有可能做我想做的事情,或者我错过了什么?

编辑:所以我添加了一些代码来解决评论。也就是说,我在测试中犯了一个方法名称错误(

getMpgResponse
而不是
getMonerisResponse
)。此外,
mpgHttpsPost
是用于调用 Moneris 网关的类的名称。我添加了
$monerisGateway
变量的实例化,因此更明显的是它与我的测试中的类相同。希望这有帮助。

php laravel unit-testing phpunit
1个回答
0
投票

不管怎样,我终于知道是怎么回事了。结果 XML 字符串在开头有一个换行符。我删除了它,一切开始完美运行:

$this->mpgXmlString = '<?xml version="1.0" standalone="yes"?>
    <response>
        <receipt>
            <ReceiptId>T65f9dae711fb5-319</ReceiptId>
            <ReferenceNum>660053720012340910</ReferenceNum>
            <ResponseCode>027</ResponseCode>
            <ISO>01</ISO>
            <AuthCode>KN6128</AuthCode>
            <TransTime>14:35:20</TransTime>
            <TransDate>2024-03-19</TransDate>
            <TransType>01</TransType>
            <Complete>true</Complete>
            <Message>APPROVED           *                    =</Message>
            <TransAmount>10.31</TransAmount>
            <CardType>M</CardType>
            <TransID>277630-0_718</TransID>
            <TimedOut>false</TimedOut>
            <BankTotals>null</BankTotals>
            <Ticket>null</Ticket>
            <CorporateCard>false</CorporateCard>
            <MessageId>1F4079525206486</MessageId>
            <AvsResultCode>R</AvsResultCode>
            <ITDResponse>null</ITDResponse>
            <CvdResultCode>1P</CvdResultCode>
            <IsVisaDebit>false</IsVisaDebit>
        </receipt>
    </response>';
© www.soinside.com 2019 - 2024. All rights reserved.