好的,这是上下文。我在 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
变量的实例化,因此更明显的是它与我的测试中的类相同。希望这有帮助。
不管怎样,我终于知道是怎么回事了。结果 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>';