【发布时间】:2022-01-27 14:14:57
【问题描述】:
我正在编写 PHPUnit 测试并运行覆盖测试。我承认很难达到 100% 的覆盖率,但是,我想尽可能接近。在以下场景中,如何在子句中模拟变量以测试代码块?
class CalendarClientService
{
/** @var array SCOPES */
public const SCOPES = [Google_Service_Calendar::CALENDAR];
/** @var string ACCESS_TYPE */
public const ACCESS_TYPE = "offline";
/** @var string CALENDAR_ID */
public const CALENDAR_ID = "primary";
/** @var int MAX_RESULTS */
public const MAX_RESULTS = 25;
/** @var string ORDER_BY */
public const ORDER_BY = "startTime";
/** @var bool SINGLE_EVENTS */
public const SINGLE_EVENTS = true;
/** @var string|null TIME_MIN */
public const TIME_MIN = null;
/** @var bool CACHE_TIME_TO_LIVE */
public const CACHE_TIME_TO_LIVE = 604800;
/** @var string */
public string $clientSecretPath = "";
/** @var StorageAdapterFactoryInterface */
protected StorageAdapterFactoryInterface $storageAdapterFactory;
/** @var StorageInterface */
protected StorageInterface $storageInterfaceCache;
/**
* CalendarClientService constructor.
* @param string $clientSecretPath
* @param StorageAdapterFactoryInterface $storageAdapterFactory
* @param StorageInterface $storageInterfaceCache
*/
public function __construct(
string $clientSecretPath,
StorageAdapterFactoryInterface $storageAdapterFactory,
StorageInterface $storageInterfaceCache
) {
$this->clientSecretPath = $clientSecretPath;
$this->storageAdapterFactory = $storageAdapterFactory;
$this->storageInterfaceCache = $storageInterfaceCache;
}
/** @return string */
public function getClientSecretPath()
{
return $this->clientSecretPath;
}
/** @param string $secretFile */
public function setClientSecretPath(string $secretFile)
{
$this->clientSecretPath = $secretFile;
}
/**
* @param array
* @return Google_Service_Calendar_Event
*/
public function getGoogleServiceCalendarEvent($eventData)
{
return new Google_Service_Calendar_Event($eventData);
}
/**
* @param string
* @return Google_Service_Calendar_EventDateTime
*/
public function getGoogleServiceCalendarEventDateTime($dateTime)
{
$eventDateTime = new Google_Service_Calendar_EventDateTime();
$eventDateTime->setDateTime(Carbon::parse($dateTime)->toW3cString());
$eventDateTime->setTimeZone(Carbon::parse($dateTime)->timezone->getName());
return $eventDateTime;
}
/**
* @param Google_Client $client
* @return Events
*/
public function getGoogleServiceCalendarResourceEvents(Google_Client $client)
{
$service = new Google_Service_Calendar($client);
return $service->events;
}
/**
* @param int
* @return array
* @throws Exception
* @throws ExceptionInterface
*/
public function getEventData($id)
{
$client = $this->getClient();
if (!$this->authenticateClient($client)) {
return [
"error" => "authentication",
"url" => filter_var($client->createAuthUrl(), FILTER_SANITIZE_URL),
];
}
$service = $this->getGoogleServiceCalendarResourceEvents($client);
return ["event" => $service->get(self::CALENDAR_ID, $id)];
}
/**
* @return Google_Client
* @throws Exception
*/
public function getClient()
{
$client = new Google_Client();
$client->setApplicationName(Module::MODULE_NAME);
$client->setScopes(self::SCOPES);
$client->setAuthConfig($this->clientSecretPath);
$client->setAccessType(self::ACCESS_TYPE);
return $client;
}
/**
* @param Google_Client $client
* @return bool
* @throws ExceptionInterface
*/
public function authenticateClient(Google_Client $client)
{
if ($this->storageInterfaceCache->hasItem("api_access_token")) {
$accessToken = json_decode($this->storageInterfaceCache->getItem("api_access_token"), true);
if ($accessToken["error"] == "invalid_grant" || empty($accessToken)) {
$this->storageInterfaceCache->removeItem("api_access_token");
} else {
$this->storageInterfaceCache->setItem("api_access_token", json_encode($accessToken));
$client->setAccessToken($accessToken);
}
}
if ($client->isAccessTokenExpired()) {
$tokenValid = false;
if ($client->getRefreshToken()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
$accessToken = $client->getAccessToken();
$this->storageInterfaceCache->setItem("api_access_token", json_encode($accessToken));
$tokenValid = true;
} else {
$helper = new Helper();
if(!$helper->verifyAuthCode($_GET["code"])){
return $tokenValid;
}
$authCode = $_GET["code"];
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
if ($accessToken["error"] == "invalid_grant" || empty($accessToken)) {
$this->storageInterfaceCache->removeItem("api_access_token");
} else {
$this->storageInterfaceCache->setItem("api_access_token", json_encode($accessToken));
$client->setAccessToken($accessToken);
$tokenValid = true;
}
}
} else {
$tokenValid = true;
}
return isset($tokenValid) ? $tokenValid : false;
}
我想在 authenticateClient 方法中测试从顶部开始的第 6 行,并想模拟这个子句 $accessToken["error"] == "invalid_grant" || empty($accessToken)。
现在怎么办?
编辑:这是我写的一个测试。现在无论我在$this->storageInterfaceCacheMock->method("getItem") 中模拟什么值,它总是返回空$accessToken。我还附上了图片,以便更好地了解正在发生的事情以及我想要什么。
public function testGetEventDataReturnsArrayOnSuccessfulAuthenticateClientThroughCache()
{
$this->storageInterfaceCacheMock->method("hasItem")->willReturn(true);
$this->storageInterfaceCacheMock->method("getItem")->willReturn(json_encode('{"access_token":"ya29.a0ARrdaM99pJTf1XzmD1ngxAH3XJud8lvHb0aTaOOABYdfdhsdfgsdfgVD9OoH4heiKoskDF7DMkHj1_aPuWIO5TE14KHJidFf66xwn_pTCkkSow6Kg4lRHwGrNQBQGI8sPlgnFO5U5hJvYdqgxDMHEqw1TER2w","expires_in":3599,"scope":"https:\/\/www.googleapis.com\/auth\/calendar","token_type":"Bearer","created":1637312218,"refresh_token":"1\/\/03psr5omKiljUCgYFDHDGJHGSHSNwF-L9Iraor5zcfe-h3BeCHSFGSDFGDGJHjy4UnEtKj974LXthS5bWexQcjviVGfJsdfGHSHgIrDn6Yk"}'));
$this->assertIsArray($this->calendarClientService->getEventData(1));
}
下面提到了另一个未按要求执行的测试。 (也可以在屏幕截图中看到)
public function testAccessTokenIsExpiredAndGotRefreshToken()
{
$this->googleClientMock->method("isAccessTokenExpired")->willReturn(true);
$this->googleClientMock->method("getRefreshToken")->willReturn(true);
$this->googleClientMock->method("fetchAccessTokenWithRefreshToken")->willReturnSelf();
$this->googleClientMock->method("getAccessToken")->willReturnSelf();
$this->assertTrue($this->calendarClientService->authenticateClient($this->googleClientMock));
}
【问题讨论】:
标签: phpunit code-coverage