$name, 'data' => $data, 'options' => $options]; } } } namespace Tests\App\Controllers\View { use App\Controllers\View\ReimbursementController; use CodeIgniter\Database\BaseBuilder; use CodeIgniter\Database\BaseConnection; use CodeIgniter\Database\BaseResult; use CodeIgniter\Test\CIUnitTestCase; use Config\Services; class TestableReimbursementController extends ReimbursementController { public function __construct() { // Skip the real parent constructor so we can inject mocks. } public function setDb(BaseConnection $db): self { $this->db = $db; return $this; } } class FakeRenderer { private array $data = []; private array $lastRender = []; public function setData(?array $data = null): self { $this->data = $data ?? []; return $this; } public function render(string $view, array $data = [], $options = null) { $this->lastRender = [ 'view' => $view, 'data' => $data ?: $this->data, 'options' => $options, ]; return 'fake-rendered:' . $view; } public function getLastRender(): array { return $this->lastRender; } } class ReimbursementControllerTest extends CIUnitTestCase { private TestableReimbursementController $controller; private FakeRenderer $renderer; protected function setUp(): void { parent::setUp(); $this->renderer = new FakeRenderer(); Services::injectMock('renderer', $this->renderer); $result = $this->createMock(BaseResult::class); $result->method('getResultArray')->willReturn([ [ 'id' => 5, 'expense_receipt' => 'uploads/path/expense_receipt.pdf', 'receipt_path' => null, ], [ 'id' => 6, 'expense_receipt' => null, 'receipt_path' => 'uploads/receipt_path.pdf', ], ]); $builder = $this->createMock(BaseBuilder::class); $builder->method('select')->willReturnSelf(); $builder->method('join')->willReturnSelf(); $builder->method('where')->willReturnSelf(); $builder->method('orderBy')->willReturnSelf(); $builder->method('get')->willReturn($result); $db = $this->createMock(BaseConnection::class); $db->method('table')->willReturn($builder); $this->controller = new TestableReimbursementController(); $this->controller->setDb($db); } public function testUnderProcessingBuildsViewWithExpenses() { $result = $this->controller->underProcessing(); $this->assertSame('fake-rendered:reimbursements/under_processing', $result); $rendered = $this->renderer->getLastRender(); $this->assertSame('reimbursements/under_processing', $rendered['view']); $expenses = $rendered['data']['expenses']; $this->assertCount(2, $expenses); $first = $expenses[0]; $this->assertSame(site_url('receipts/expense_receipt.pdf'), $first['expense_receipt_url']); $this->assertSame( 'Reimburse', $first['action'] ); $second = $expenses[1]; $this->assertSame(site_url('receipts/receipt_path.pdf'), $second['expense_receipt_url']); $this->assertSame( 'Reimburse', $second['action'] ); } } }