我必须为显示在我的网站上的登录对话框编写一个测试,但是此登录对话框只有两个,只有两个访问点。理想情况下,我的页面对象应反映对此登录对话框的受限访问。
clickLogin
上使用Header
时,会弹出LoginDialog
postComment
上使用Article
时,您没有登录(为了简单起见,我们假设您不是这样),会弹出LoginDialog
。 这是代码中的样子:
new LoginDialog().login(); // shouldn't be allowed
new Header().clickLogin().login(); // should be allowed
new Article().postComment().login() // should be allowed
我想出了一种解决此问题的方法。
LoginDialog
只有两个构造函数,这两个构造函数都接受一个只能用Header
或Article
构造的对象。public class LoginDialogTest extends WebTest {
@Test
public void testLoginDialogFromHeader {
new HomePage().loadPage();
new Header().clickLogin().login();
verifyLoggedIn();
}
@Test
public void testLoginDialogFromArticleComment {
new ArticlePage(42).loadPage(); // Load an article with id=42
new Article().postComment().login();
verifyLoggedIn();
}
}
public class LoginDialog {
public LoginDialog(Article.CommentButton commentButton) {
}
public LoginDialog(Header.LoginButton loginButton) {
}
public void login() {
}
}
public class Article {
public class CommentButton {
private CommentButton() {
}
public LoginDialog click() {
return new LoginDialog(this);
}
}
public LoginDialog postComment() {
return new CommentButton().click();
}
}
public class Header {
public class LoginButton {
public LoginDialog click() {
return new LoginDialog(this);
}
}
public LoginDialog clickLogin() {
return new LoginButton().click();
}
}
我的问题是这是否是现有模式,如果存在,它的名称是什么?如果不是,那将是一个好名字吗?
最佳答案
我认为这是确保仅Header
或Article
可以创建LoginDialog
的一种简单方法:
public class LoginDialog {
private LoginDialog() {
... code to construct
}
public interface Constructor {
LoginDialog newLoginDialog();
}
private static class ConstructorImpl implements Constructor {
public LoginDialog newLoginDialog() {
return new LoginDialog();
}
}
private static ConstructorImpl constructor;
static {
constructor = new ConstructorImpl();
Header.provideLoginDialogConstructor(constructor);
Article.provideLoginDialogConstructor(constructor);
}
}
并在
Header
和Article
中提供一个公共的provideLoginDialogConstructor
方法:private static LoginDialog.Constructor constructor;
public static void provideLoginDialogConstructor(LoginDialog.Constructor constructor) {
Header.constructor = constructor; // or Article.constructor
}
以及当这些类需要构造
LoginDialog
时:if (!loggedIn()) {
return constructor.newLoginDialog();
} else {
return null;
}
由于
LoginDialog
类决定要使哪些类具有其私有对象来构造LoginDialog
,因此,另一个类应该没有办法使用常规方法来构造一个类([使用反射可能会有棘手的方法])。注意:我尚未对此进行测试。