使用Playwright Java复用Page做PowerApps测试时遇空指针异常
问题分析与解决方案
核心原因
你的NullPointerException是由于测试类中的page变量未被正确初始化,具体原因有两点:
- JUnit 4中
@BeforeAll修饰的方法必须是static类型,否则该方法不会被执行。你当前的createPage()是非静态方法,导致page始终为null,调用page.navigate()时触发空指针异常。 - 调用
persistentLogin(true)时如果没有静态导入PersistentLogin类的方法,也会导致编译/执行错误,无法正确获取Page实例。
另外,原PersistentLogin类的实现存在资源泄漏问题:每次调用都会创建新的Playwright实例,未做复用和关闭处理,长期运行会消耗大量资源。
修正步骤
1. 修复测试类的注解与方法调用
改用JUnit 4的@Before(对应每个测试用例执行前初始化),并确保正确调用PersistentLogin的静态方法:
import org.junit.Before; import org.junit.Test; import org.junit.AfterClass; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import com.microsoft.playwright.Page; import com.microsoft.playwright.options.AriaRole; public class TestsExample { // 注意URL必须带http/https协议头 private String goToUrl = "https://www.example.com"; private Page page; @Before // 每个测试用例执行前初始化Page void createPage(){ // 明确调用PersistentLogin的静态方法 page = PersistentLogin.getPersistentPage(); } @Test public void saveHolidayPeriodFromAdminScreenTest(){ page.navigate(goToUrl); page.frameLocator("#fullscreen-app-host") .getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName("Run as Admin")) .click(); assertThat(page.frameLocator("#fullscreen-app-host").getByText("Preferences - New Summer Leave 2023")).isVisible(); } @AfterClass // 所有测试结束后清理资源 public static void cleanUp(){ PersistentLogin.tearDown(); } }
2. 优化PersistentLogin类,实现资源复用与管理
将Playwright和BrowserContext改为静态单例,避免重复创建,并添加资源清理方法:
import com.microsoft.playwright.BrowserContext; import com.microsoft.playwright.BrowserType; import com.microsoft.playwright.Page; import com.microsoft.playwright.Playwright; import java.nio.file.Path; import java.nio.file.Paths; public class PersistentLogin { private static final String USER_DATA_DIR_PATH = "/Users/user/powerAppsTesting/userData"; private static Playwright playwright; private static BrowserContext context; // 初始化Playwright与持久化上下文,仅执行一次 private static void init() { if (playwright == null) { playwright = Playwright.create(); BrowserType chromium = playwright.chromium(); Path userDataDir = Paths.get(USER_DATA_DIR_PATH); // 确保用户数据目录存在,不存在则自动创建 userDataDir.toFile().mkdirs(); // 初始化持久化上下文 context = chromium.launchPersistentContext(userDataDir, new BrowserType.LaunchPersistentContextOptions().setHeadless(true)); } } // 获取复用的Page实例 public static Page getPersistentPage() { init(); return context.newPage(); } // 关闭所有资源 public static void tearDown() { if (context != null) { context.close(); } if (playwright != null) { playwright.close(); } } }
额外检查点
- 确保
USER_DATA_DIR_PATH对应的目录有读写权限,否则持久化上下文创建失败会返回null。 - 测试用例中不要手动关闭
page,否则后续测试会无法复用上下文;所有资源清理统一在@AfterClass的tearDown()中执行。
内容的提问来源于stack exchange,提问作者gabo
相关产品推荐
相关产品推荐

