Skip to content

Commit a4bec08

Browse files
Merge pull request #19 from Vectorial1024/faker
Provide fake objects for external testing
2 parents d6db4aa + 7e5a336 commit a4bec08

File tree

5 files changed

+176
-2
lines changed

5 files changed

+176
-2
lines changed

src/AsyncTask.php

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,21 @@ public function __construct(Closure|AsyncTaskInterface $theTask, string|null $ta
114114
$this->taskID = $taskID;
115115
}
116116

117+
/**
118+
* Returns an instance of a fake AsyncTask with the same task parameters and task ID.
119+
* @return FakeAsyncTask The fake AsyncTask object for testing.
120+
*/
121+
public function fake(): FakeAsyncTask
122+
{
123+
$fakeTask = new FakeAsyncTask($this->theTask, taskID: $this->taskID);
124+
if ($this->getTimeLimit() === null) {
125+
$fakeTask->withoutTimeLimit();
126+
} else {
127+
$fakeTask->withTimeLimit($this->timeLimit);
128+
}
129+
return $fakeTask;
130+
}
131+
117132
public function __serialize(): array
118133
{
119134
// serialize only the necessary info to reduce runner cmd length
@@ -131,6 +146,18 @@ public function __unserialize($data): void
131146
] = $data;
132147
}
133148

149+
/**
150+
* Returns a status object for the started AsyncTask.
151+
*
152+
* If this task does not have an explicit task ID, a new one will be generated on-the-fly.
153+
* @return AsyncTaskStatus The status object for the started AsyncTask.
154+
*/
155+
protected function getTaskStatusObject(): AsyncTaskStatus
156+
{
157+
$taskID = $this->taskID ?? Str::ulid()->toString();
158+
return new AsyncTaskStatus($taskID);
159+
}
160+
134161
/**
135162
* Inside an available PHP process, runs this AsyncTask instance.
136163
*
@@ -192,8 +219,7 @@ public function run(): void
192219
public function start(): AsyncTaskStatus
193220
{
194221
// prepare the task details
195-
$taskID = $this->taskID ?? Str::ulid()->toString();
196-
$taskStatus = new AsyncTaskStatus($taskID);
222+
$taskStatus = $this->getTaskStatusObject();
197223

198224
// prepare the runner command
199225
$serializedTask = $this->toBase64Serial();

src/AsyncTaskStatus.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@ public function __construct(
5050
}
5151
}
5252

53+
/**
54+
* Returns an instance of a fake status object with the same task ID.
55+
* @return FakeAsyncTaskStatus The fake AsyncTaskStatus object for testing.
56+
*/
57+
public function fake(): FakeAsyncTaskStatus
58+
{
59+
return new FakeAsyncTaskStatus($this->taskID);
60+
}
61+
5362
/**
5463
* Returns the task ID encoded in base64, mainly for result checking.
5564
* @return string The encoded task ID.

src/FakeAsyncTask.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Vectorial1024\LaravelProcessAsync;
6+
7+
use Closure;
8+
9+
/**
10+
* The fake AsyncTask class for testing.
11+
*/
12+
class FakeAsyncTask extends AsyncTask
13+
{
14+
/**
15+
* Creates a FakeAsyncTask instance.
16+
*
17+
* @param \Closure|AsyncTaskInterface $theTask The task to be executed in the background.
18+
* @param string|null $taskID (optional) The user-specified task ID of this AsyncTask. Should be unique.
19+
* @see AsyncTask::fake() an alternative way of creating FakeAsyncTask instances.
20+
*/
21+
public function __construct(Closure|AsyncTaskInterface $theTask, string|null $taskID = null)
22+
{
23+
parent::__construct($theTask, taskID: $taskID);
24+
}
25+
26+
/**
27+
* Dummy overriding method to prevent the FakeAsyncTask object from actually running the specified background task.
28+
* @return void
29+
*/
30+
public function run(): void
31+
{
32+
// don't do anything!
33+
return;
34+
}
35+
36+
/**
37+
* Fakes the AsyncTask being started in the background, but does not actually start the task.
38+
* @return FakeAsyncTaskStatus The status object for the fake-started FakeAsyncTask.
39+
*/
40+
public function start(): FakeAsyncTaskStatus
41+
{
42+
return $this->getTaskStatusObject()->fake();
43+
}
44+
}

src/FakeAsyncTaskStatus.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Vectorial1024\LaravelProcessAsync;
6+
7+
/**
8+
* The fake AsyncTaskStatus class for testing. Fake async tasks are presumed to be running by default.
9+
*/
10+
class FakeAsyncTaskStatus extends AsyncTaskStatus
11+
{
12+
private bool $fakeIsRunning = true;
13+
14+
/**
15+
* Constructs a fake status object. Fake async tasks are presumed to be running by default.
16+
* @param string $fakeTaskID The task ID of the fake async task.
17+
*/
18+
public function __construct(string $fakeTaskID) {
19+
parent::__construct($fakeTaskID);
20+
}
21+
22+
/**
23+
* Returns whether the fake task is currently "running".
24+
* @return bool The faked "task is running" status.
25+
*/
26+
public function isRunning(): bool
27+
{
28+
return $this->fakeIsRunning;
29+
}
30+
31+
/**
32+
* Force the fake task to become stopped.
33+
*
34+
* Note: once stopped, the fake async task cannot be made running again. Use a new status object if the fake task needs to be restarted.
35+
* @return void
36+
*/
37+
public function fakeStopRunning(): void
38+
{
39+
$this->fakeIsRunning = false;
40+
}
41+
}

tests/FakeAsyncTaskTest.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
namespace Vectorial1024\LaravelProcessAsync\Tests;
4+
5+
use Vectorial1024\LaravelProcessAsync\AsyncTask;
6+
use Vectorial1024\LaravelProcessAsync\AsyncTaskStatus;
7+
use Vectorial1024\LaravelProcessAsync\Tests\Tasks\DummyAsyncTask;
8+
use Vectorial1024\LaravelProcessAsync\FakeAsyncTaskStatus;
9+
10+
// a series of tests that ensure the fake tasks are indeed fake while still look like the same
11+
class FakeAsyncTaskTest extends BaseTestCase
12+
{
13+
public function testFakeTaskDoesNotRun()
14+
{
15+
// the fake task should not even run
16+
$testFileName = $this->getStoragePath("testFakeTaskDoesNotRun.txt");
17+
$task = new AsyncTask(new DummyAsyncTask("Hello world!", $testFileName));
18+
$fakeTask = $task->fake();
19+
20+
// fake start it
21+
$fakeTask->start();
22+
sleep(1);
23+
// there should have no file outputs
24+
$this->assertFileDoesNotExist($testFileName);
25+
}
26+
27+
public function testFakeTaskSameParams()
28+
{
29+
// the fake task should preserve its parameters
30+
$testFileName = $this->getStoragePath("testFakeTaskSameDetails.txt");
31+
$task = new AsyncTask(new DummyAsyncTask("Hello world!", $testFileName));
32+
$randomDuration = rand(1, 10);
33+
$task->withTimeLimit($randomDuration);
34+
35+
// fake it...
36+
$fakeTask = $task->fake();
37+
// ...and the parameters stay the same
38+
$this->assertEquals($task->getTimeLimit(), $fakeTask->getTimeLimit());
39+
40+
// it is difficult to test the task ID since it would be exposing something that should not be exposed, so we will just have to believe it.
41+
}
42+
43+
public function testFakeTaskStatus()
44+
{
45+
$taskID = "testFakeTaskStatus";
46+
$taskStatus = new AsyncTaskStatus($taskID);
47+
$fakeTaskStatusFromFake = $taskStatus->fake();
48+
$fakeTaskStatusFromNew = new FakeAsyncTaskStatus($taskID);
49+
50+
// should have same task ID
51+
$this->assertEquals($taskStatus->getEncodedTaskID(), $fakeTaskStatusFromFake->getEncodedTaskID());
52+
$this->assertEquals($taskStatus->getEncodedTaskID(), $fakeTaskStatusFromNew->getEncodedTaskID());
53+
}
54+
}

0 commit comments

Comments
 (0)