Summer Sale! All accounts are 50% off this week.

MostofaL's avatar

How to Set HTTP_HOST while Integration Testing on multitenant app with different domain

I have a multitenant application, in which every tenant has a specific domain or subdomain. some of these tenants like the landlord have some particular features and tools.

I've managed to initialize HTTP_HOST in PHPUnit by adding the following line: <server name='HTTP_HOST' value='mydomain.local' /> but doing this, I must manually change the HTTP_HOST every time and re-run the tests to cover all the scenarios.

is there any way to set this dynamically?

Apparently using ->withHeaders(['HTTP_HOST' => 'mydomain.local']) won't work.

0 likes
5 replies
tisuchi's avatar
tisuchi
Best Answer
Level 70

@mostafaalotfi@gmail.com There are a few ways you can set the HTTP_HOST dynamically while integration testing on a multitenant application with different domains:

  1. Use environment variables to set the HTTP_HOST: You can set the HTTP_HOST in an environment variable, and then use that variable in your tests. This way, you can change the value of the environment variable without modifying the code of your tests.
public function testTenant1() {
    putenv("HTTP_HOST=tenant1.com");
    $response = $this->get('/');
    $response->assertStatus(200);
}

public function testTenant2() {
    putenv("HTTP_HOST=tenant2.com");
    $response = $this->get('/');
    $response->assertStatus(200);
}
  1. Use a loop to iterate through all the tenants: You can use a loop to iterate through all the tenants, and set the HTTP_HOST to the domain of the current tenant.
public function testTenant() {
    $tenants = ['tenant1.com', 'tenant2.com'];
    foreach ($tenants as $tenant) {
        $_SERVER['HTTP_HOST'] = $tenant;
        $response = $this->get('/');
        $response->assertStatus(200);
    }
}
  1. Use a custom middleware: you can create a custom middleware that sets the HTTP_HOST based on the tenant's domain, and then use that middleware in your tests.
public function testTenant() {
    $tenants = ['tenant1.com', 'tenant2.com'];
    foreach ($tenants as $tenant) {
        $response = $this->get('/', [
            'HTTP_HOST' => $tenant,
        ]);
        $response->assertStatus(200);
    }
}

It's important to note that, to change the HTTP_HOST and test the different scenarios, you have to make sure that you are using the current tenant's domain in all the requests, not only in the first one.

1 like
martinbean's avatar

@tisuchi Yeah, you should be using data providers as the framework isn’t reset after a request in a test, so you may find issues relating to state being persisted when making subsequent tests in a single test case.

/**
 * @dataProvider tenantsDataProvider
 */
public function testCanViewTenantHomePage(string $host): void
{
    $host = Str::start($host, 'https://');

    $this->get($host)->assertOk();
}

public function tenantsDataProvider(): array
{
    return [
        'tenant1.com' => ['tenant1.com'],
        'tenant2.com' => ['tenant2.com'],
    ];
}

This will run the test case multiple times with a different host value each time, meaning each HTTP request will be isolated.

1 like

Please or to participate in this conversation.