Senior SDETFrameworks & Design PatternsFree question
How do you use dependency injection in test frameworks?
60-second answer
Dependency injection means a test or class receives its dependencies from outside instead of creating them itself. In test frameworks that gives isolation, easy swapping of implementations like real versus fake services, and clean lifecycle management. In Playwright, fixtures are the DI mechanism. In Cucumber Java I use PicoContainer or Spring to share a scenario-scoped context between step definition classes. In TestNG or JUnit I can use Guice or Spring's test support. It avoids static singletons and global state, which is what usually breaks parallel execution.
Explanation
- Scope matters: per test (page, data), per worker/thread (browser), per suite (config).
- Constructor injection keeps dependencies explicit.
- DI makes it simple to inject a fake clock, fake gateway, or a different environment config.
- Don't over-engineer: for small suites, fixtures or a simple factory may be enough.
Example
Cucumber steps split across CartSteps, CheckoutSteps and PaymentSteps share one ScenarioContext (driver, user, cart) injected by PicoContainer, created fresh for each scenario.
Sample code
public class ScenarioContext {
public final WebDriver driver = DriverFactory.create(Config.get("browser"));
public User user;
public String orderId;
}
public class CartSteps {
private final ScenarioContext ctx;
public CartSteps(ScenarioContext ctx) { this.ctx = ctx; } // injected
@Given("a logged-in premium customer")
public void loggedInPremium() {
ctx.user = UserBuilder.aUser().premium().create(new UserApi());
new LoginFlow(ctx.driver).asUser(ctx.user);
}
}