Q10 of 17 · Framework design
How is dependency injection used in test automation frameworks, and what problem does it solve?
Framework designSeniorframework-designdependency-injectiondispringfixturesadvanced
Short answer
Short answer: DI in test frameworks removes hardcoded construction of dependencies (driver, API clients, DB helpers) inside test classes. Instead, dependencies are created once per scenario/test and injected — enabling easier mocking, parallel isolation, and framework replacement without touching tests.
Detail
The problem without DI:
public class LoginTest {
// Hardcoded dependency creation — couples test to implementation
private WebDriver driver = new ChromeDriver();
private LoginPage loginPage = new LoginPage(driver);
@Test
public void validLoginTest() { ... }
}
Changing to Firefox means changing every test class. Tests are impossible to unit-test because you can't swap ChromeDriver for a mock.
With DI — Spring (Java):
@SpringBootTest
@ExtendWith(SpringExtension.class)
public class LoginTest {
@Autowired
private WebDriver driver; // Created by Spring, injected here
@Autowired
private LoginPage loginPage;
@Test
public void validLoginTest() { ... }
}
@Configuration
public class WebDriverConfig {
@Bean
@Scope("prototype") // new instance per test
public WebDriver webDriver() {
return new ChromeDriver(options());
}
}
Playwright fixtures as DI:
// Playwright's fixture system IS dependency injection
const test = base.extend<{ loginPage: LoginPage; apiClient: ApiClient }>({
loginPage: async ({ page }, use) => {
await use(new LoginPage(page));
},
apiClient: async ({}, use) => {
const client = new ApiClient(config.apiUrl);
await client.authenticate();
await use(client);
await client.logout();
},
});
test('user can view orders after login', async ({ loginPage, apiClient }) => {
// loginPage and apiClient injected, created fresh per test
});
Benefits:
- Swap ChromeDriver for a mock in unit tests without touching test code
- Each parallel test gets its own scoped dependencies — no cross-test state
- Centralised driver/client construction — one config change applies everywhere
// WHAT INTERVIEWERS LOOK FOR
The problem DI solves (tight coupling, no mockability). At least one concrete implementation (Spring, PicoContainer, or Playwright fixtures). Parallel isolation benefit.