我必须为显示在我的网站上的登录对话框编写一个测试,但是此登录对话框只有两个,只有两个访问点。理想情况下,我的页面对象应反映对此登录对话框的受限访问。

  • 当您在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只有两个构造函数,这两个构造函数都接受一个只能用HeaderArticle构造的对象。
    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();
        }
    }
    

    我的问题是这是否是现有模式,如果存在,它的名称是什么?如果不是,那将是一个好名字吗?

    最佳答案

    我认为这是确保仅HeaderArticle可以创建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);
        }
    }
    

    并在HeaderArticle中提供一个公共的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,因此,另一个类应该没有办法使用常规方法来构造一个类([使用反射可能会有棘手的方法])。

    注意:我尚未对此进行测试。

    10-06 09:37