# Playwright Java – 夹具 (Fixtures)、钩子 (Hooks) 与测试数据
## JUnit 5 Playwright 扩展 (自定义夹具)
将浏览器生命周期封装在可复用的 JUnit 5 扩展中:
java
package com.company.tests.base;
import com.microsoft.playwright.*;
import org.junit.jupiter.api.extension.*;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class PlaywrightExtension
implements BeforeEachCallback, AfterEachCallback, ParameterResolver {
private static final Map pageMap = new ConcurrentHashMap();
@Override
public void beforeEach(ExtensionContext ctx) {
Playwright pw = Playwright.create();
Browser browser = pw.chromium().launch(new BrowserType.LaunchOptions().setHeadless(true));
BrowserContext context = browser.newContext();
Page page = context.newPage();
pageMap.put(ctx.getUniqueId(), page);
ctx.getStore(ExtensionContext.Namespace.GLOBAL).put("playwright", pw);
ctx.getStore(ExtensionContext.Namespace.GLOBAL).put("browser", browser);
ctx.getStore(ExtensionContext.Namespace.GLOBAL).put("context", context);
}
@Override
public void afterEach(ExtensionContext ctx) {
pageMap.remove(ctx.getUniqueId());
closeIfNotNull(ctx.getStore(ExtensionContext.Namespace.GLOBAL).remove("context", BrowserContext.class));
closeIfNotNull(ctx.getStore(ExtensionContext.Namespace.GLOBAL).remove("browser", Browser.class));
closeIfNotNull(ctx.getStore(ExtensionContext.Namespace.GLOBAL).remove("playwright", Playwright.class));
}
@Override
public boolean supportsParameter(ParameterContext param, ExtensionContext ext) {
return param.getParameter().getType() == Page.class;
}
@Override
public Object resolveParameter(ParameterContext param, ExtensionContext ext) {
return pageMap.get(ext.getUniqueId());
}
private void closeIfNotNull(AutoCloseable obj) {
if (obj != null) try { obj.close(); } catch (Exception ignored) {}
}
}
// 用法:
@ExtendWith(PlaywrightExtension.class)
class CheckoutTest {
@Test
void shouldCompleteCheckout(Page page) {
// Page 会自动注入
new LoginPage(page).navigate().loginAs("
[email protected]", "pass");
}
}
---
## 测试数据工厂
java
package com.company.tests.utils;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.datafaker.Faker;
import java.io.InputStream;
import java.util.List;