Java11嵌套类结合流畅设计重构Selenium自动化测试项目求助
Hey there! Let's work through refactoring your Selenium/TestNG project to use fluent design while keeping those nested page object classes—since you're comfortable with C# but new to Java's nested class behavior, I'll break this down step by step to get that smooth method chain working.
Key Issues in Your Current Code
Before diving into fixes, let's call out what's blocking the fluent flow:
- The
AddEditUserInformationnested class is static, so it has no link to the parentUserAdminPageinstance—you can't seamlessly return to parent methods after using nested class logic. - Some methods return
voidor incorrect types (likeFirstName_txtbxreturningUserAdminPageinstead of the nested class), which breaks the chain. - Your test code's syntax for calling nested class methods isn't valid in Java—you need an instance of the nested class to call its methods, not just the class name.
Refactored Page Object Code
Here's the adjusted UserAdminPage that preserves nested classes and enables fluent calls:
import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class UserAdminPage { private final RemoteWebDriver driver; public UserAdminPage(RemoteWebDriver driver) { this.driver = driver; PageFactory.initElements(driver, this); } // Entry point for fluent chain (matches your existing using pattern) public static UserAdminPage using(RemoteWebDriver driver) { return new UserAdminPage(driver); } // Non-static nested class (inner class) - automatically holds a reference to the parent UserAdminPage instance public class AddEditUserInformation { @FindBy(name = "firstName") private WebElement firstNameTxtbx; @FindBy(name = "lastName") private WebElement lastNameTxtbx; // Return the nested class instance to keep the chain going for related actions public AddEditUserInformation setFirstName(String firstName) { firstNameTxtbx.sendKeys(firstName); return this; } // Return the parent UserAdminPage instance to jump back to parent-level actions public UserAdminPage setLastName(String lastName) { lastNameTxtbx.sendKeys(lastName); return UserAdminPage.this; // Reference the parent class instance } } // Method to get the nested class instance - starts the nested action chain public AddEditUserInformation addEditUser() { return new AddEditUserInformation(); } @FindBy(id = "AccountsList") private WebElement accountNameDropdown; // Return parent instance to continue the chain public UserAdminPage selectAccountName() { accountNameDropdown.click(); return this; } @FindBy(id = "Save_button") private WebElement saveBtn; // Optional: return parent instance if you want to chain more actions after save public UserAdminPage save() { saveBtn.click(); return this; } }
Fluent Test Case Example
Now your test code becomes a readable, uninterrupted chain—perfect for non-developers to follow:
UserAdminPage.using(driver) .selectAccountName() .addEditUser() .setFirstName("John") .setLastName("Doe") .save();
Critical Concepts Explained
Non-Static Nested Classes (Inner Classes)
Unlike static nested classes, Java inner classes automatically hold a reference to their parent class instance. This lets us easily jump back to parent methods (likesave()) after completing nested actions usingUserAdminPage.this.Consistent Return Types
Every method that needs to keep the fluent chain alive returns either:this(the current class instance) to continue actions in the same scope- The target class instance (parent or nested) to switch scopes smoothly
Readable Naming
I renamed methods to use action-based names (e.g.,selectAccountName()instead ofAccountName_dropdwn(),setFirstName()instead ofFirstName_txtbx())—this makes the test case read like plain English, which is key for non-developer users.
If You Must Keep Static Nested Classes
If you need AddEditUserInformation to stay static (for specific project constraints), you can manually pass the parent instance to the nested class constructor:
// Static nested class with parent reference public static class AddEditUserInformation { private final UserAdminPage parentPage; public AddEditUserInformation(UserAdminPage parentPage) { this.parentPage = parentPage; } public AddEditUserInformation setFirstName(String firstName) { PageFactory.initElements(parentPage.driver, this); firstNameTxtbx.sendKeys(firstName); return this; } public UserAdminPage setLastName(String lastName) { lastNameTxtbx.sendKeys(lastName); return parentPage; } } // Parent class method to get nested instance public AddEditUserInformation addEditUser() { return new AddEditUserInformation(this); }
This achieves the same fluent chain while keeping the nested class static.
内容的提问来源于stack exchange,提问作者Handsome Coder

