MagratheaPHP2
Up to date Narrative last written —; no source changes since. Method signatures below are reflected live.

Testing with MagratheaPHP2

Directory: src/Tests/ Namespace: Magrathea2\Tests

The framework ships with built-in test utilities to help you write unit tests for your models, APIs, and controllers.


Test Infrastructure Files

FileDescription
src/Tests/TestsManager.phpTest runner and assertion manager
src/Tests/TestsHelper.phpAssertion helpers
src/Tests/phpUnitBootstrap.phpPHPUnit bootstrap for database and framework setup

PHPUnit Bootstrap

The phpUnitBootstrap.php file initializes the framework for test runs. Reference it in your phpunit.xml:

<!-- phpunit.xml -->
<phpunit bootstrap="vendor/magrathea/magrathea-php2/src/Tests/phpUnitBootstrap.php">
    <testsuites>
        <testsuite name="Application">
            <directory>tests/</directory>
        </testsuite>
    </testsuites>
</phpunit>

Mocking the Database

For unit tests that shouldn't hit a real database, use Database::Mock():

use Magrathea2\DB\Database;

class ProductControlTest extends \PHPUnit\Framework\TestCase {

    protected function setUp(): void {
        Database::Instance()->Mock(); // disable real queries
    }
}

For integration tests, use Database::Instance()->SetConfig(...) to point to a test database:

protected function setUp(): void {
    Database::Instance()->SetConnectionArray([
        "host"     => "localhost",
        "database" => "test_db",
        "username" => "root",
        "password" => "",
    ])->OpenConnectionPlease();
}

Mocking Configuration

use Magrathea2\Config;

Config::Instance()->SetConfig([
    "database" => [
        "host"     => "localhost",
        "database" => "test_db",
        "username" => "root",
        "password" => "",
    ],
    "app" => [
        "name" => "Test App",
    ],
]);

Mocking ConfigApp (Database-stored Config)

use Magrathea2\ConfigApp;

ConfigApp::Instance()->Mock([
    "feature_flag_x" => "true",
    "max_retries"    => "3",
]);

// Use it
$flag = ConfigApp::Instance()->GetBool("feature_flag_x"); // true

// Restore
ConfigApp::Instance()->UnMock();

Testing Models

use App\Models\Product;
use PHPUnit\Framework\TestCase;

class ProductModelTest extends TestCase {

    public function testFieldAssignment(): void {
        $product = new Product();
        $product->name  = "Widget";
        $product->price = 9.99;

        $this->assertEquals("Widget", $product->name);
        $this->assertEquals(9.99, $product->price);
    }

    public function testToArray(): void {
        $product = new Product();
        $product->name  = "Widget";
        $product->price = 9.99;

        $arr = $product->ToArray();
        $this->assertArrayHasKey("name", $arr);
        $this->assertEquals("Widget", $arr["name"]);
    }

    public function testIsEmpty(): void {
        $product = new Product();
        $this->assertTrue($product->IsEmpty());

        $product->SetPK(1);
        $this->assertFalse($product->IsEmpty());
    }
}

Testing API Controllers

use App\Api\ProductApiControl;
use PHPUnit\Framework\TestCase;

class ProductApiControlTest extends TestCase {

    private ProductApiControl $ctrl;

    protected function setUp(): void {
        // Mock the database before tests
        \Magrathea2\DB\Database::Instance()->Mock();
        $this->ctrl = new ProductApiControl();
    }

    public function testListReturnsArray(): void {
        $result = $this->ctrl->List();
        $this->assertIsArray($result);
    }
}

Testing the Query Builder

The query builder doesn't execute SQL — it just builds strings. This makes it very easy to test:

use Magrathea2\DB\Query;
use PHPUnit\Framework\TestCase;

class QueryBuilderTest extends TestCase {

    public function testBasicSelect(): void {
        $sql = Query::Select()
            ->Table("products")
            ->Where("active = 1")
            ->Order("name ASC")
            ->Limit(10)
            ->SQL();

        $this->assertStringContainsString("FROM products", $sql);
        $this->assertStringContainsString("WHERE active = 1", $sql);
        $this->assertStringContainsString("ORDER BY name ASC", $sql);
        $this->assertStringContainsString("LIMIT 10", $sql);
    }

    public function testInsert(): void {
        $sql = Query::Insert()
            ->Table("products")
            ->Values(["name" => "Widget", "price" => 9.99])
            ->SQL();

        $this->assertStringContainsString("INSERT INTO products", $sql);
        $this->assertStringContainsString("Widget", $sql);
    }
}

Simulating Email

use Magrathea2\MagratheaMail;
use PHPUnit\Framework\TestCase;

class MailTest extends TestCase {

    public function testEmailNotSentInTest(): void {
        $mail = new MagratheaMail();
        $mail->Simulate(); // don't actually send

        $mail->SetTo("test@example.com")
             ->SetFrom("noreply@app.com")
             ->SetSubject("Test")
             ->SetHTMLMessage("<p>Hello</p>");

        $result = $mail->Send();
        $this->assertTrue($result); // simulate always returns true
    }
}

TestsManager (Built-in Runner)

The TestsManager provides a lightweight assertion runner without PHPUnit, useful for integration health checks:

use Magrathea2\Tests\TestsManager;

$tests = new TestsManager();

$tests->Add("Database connects", function() {
    Database::Instance()->OpenConnectionPlease();
    return true;
});

$tests->Add("Config loads", function() {
    $host = Config::Instance()->GetConfig("database/host");
    return !empty($host);
});

$tests->Run();
// Outputs pass/fail for each registered test

Notes