拦截器在单元测试

时间:2015-08-10 05:35:43

标签: unit-testing ejb interceptor glassfish-embedded

我得到Interceptors在应用服务器上工作。我有注释EJB:

@Stateless
@Named("accountsEJB")
public class AccountsEJB {

  @PersistenceContext(unitName = "weducationPU")
  private EntityManager em;

  // . . . other methods

  @WithLog
  @Restricted(allowedRoles = {}) // Allowed only for admin
  public Account save(Account item) {
    if (item.getId() == 0) {
      em.persist(item);
      return item;
    } else {
      return em.merge(item);
    }
  }

  @WithLog
  @Restricted(allowedRoles = {}) // Allowed only for admin
  public void delete(final Account item) {
    Account a = em.find(Account.class, item.getId());
    if (null != a) {
      em.remove(a);
    }
  }  
}

空角色列表表示仅允许角色admin

此EJB的单元测试文件

public class AccountsEJBTest {

  private static EJBContainer container;
  private static AccountsEJB ejb;

  @BeforeClass
  public static void setUpClass() {
    try {
      Map<String, Object> properties = new HashMap<>();
      properties.put(EJBContainer.MODULES, new File("target/classes"));
      properties.put("org.glassfish.ejb.embedded.glassfish.installation.root", "glassfish");
      properties.put(EJBContainer.APP_NAME, "weducation");
      container = EJBContainer.createEJBContainer(properties);
      ejb = (AccountsEJB) container.getContext().lookup("java:global/weducation/classes/AccountsEJB");
      System.out.println("AccountsEJBTest running...");
    } catch (NamingException e) {
      fail("Container init error: " + e.getMessage());
    }
  }

  @AfterClass
  public static void tearDownClass() {
    if (null != container) {
      container.close();
    }
    System.out.println("AccountsEJBTest finished");
  }

  private boolean equals(Account source, Account result) {
    if (!source.getFullName().contentEquals(result.getFullName())) return false;
    if (!source.getLogin().contentEquals(result.getLogin())) return false;
    return source.getRole() == result.getRole();
  }

  @Test
  public void testOperations() {
    try {
      System.out.println("-->testOperations()");
      Account testAccount = new Account();
      testAccount.setFullName("Test Account");
      testAccount.setLogin("test");
      testAccount.setPassword("test");
      testAccount.setConfirm("test");
      testAccount.updatePassword();
      testAccount.setRole(AccountRole.DEPOT);
      Account savedAccount = ejb.save(testAccount);
      assertTrue(equals(testAccount, savedAccount));

      savedAccount.setFullName("Still Test Account");
      savedAccount.setLogin("test1");
      testAccount = ejb.save(savedAccount);

      assertTrue(equals(testAccount, savedAccount));

      testAccount.setPassword("testpwd");
      testAccount.setConfirm("testpwd");
      testAccount.updatePassword();
      savedAccount = ejb.save(testAccount);

      assertTrue(equals(testAccount, savedAccount));

      ejb.delete(savedAccount);
    } catch (Exception e) {
      fail("Exception class " + e.getClass().getName() + " with message " + e.getMessage());
    }
  }
}

这个测试工作。我认为,这是不正确的,因为没有登录管理员角色的用户。但为什么这种行为会受到影响呢?

更新。

@Restricted interface:

@Inherited
@InterceptorBinding
@Target({METHOD, TYPE})
@Retention(RUNTIME)
public @interface Restricted {
  @Nonbinding
  AccountRole[] allowedRoles();
}

SecurityInterceptor类

@Interceptor
@Restricted(allowedRoles = {})
public class SecurityInterceptor implements Serializable {

  @Inject
  private transient SessionMB session;

  @AroundInvoke
  public Object checkSecurity(InvocationContext context) throws Exception {
    //System.out.println("Security checker started.");
    if ((session == null) || (session.getUser() == null)) {
      throw new SecurityException("Can't get user info");
    }
    // Allow all to admin
    if (session.isAdmin()) {
      //System.out.println("It's admin.");
      return context.proceed();
    }
    // walk non administrator roles
    for (AccountRole r : getAllowedRoles(context.getMethod())) {
        // if match - accept method invocation
      if (session.getUser().getRole() == r) {
        //System.out.println("It's " + r.getDescription());
        return context.proceed();
      }
    }
    throw new SecurityException(session.getUser().getFullName()
        + " has no souch privilegies ");
  }

  private AccountRole[] getAllowedRoles(Method m) {
    if (null == m) {
      throw new IllegalArgumentException("Method is null!");
    }
    // Walk all method annotations
    for (Annotation a : m.getAnnotations()) {
      if (a instanceof Restricted) {
        return ((Restricted) a).allowedRoles();
      }
    }
    // Now - walk all class annotations
    if (null != m.getDeclaringClass()) {
      for (Annotation a : m.getDeclaringClass().getAnnotations()) {
        if (a instanceof Restricted) {
          return ((Restricted) a).allowedRoles();
        }
      }
    }
    // if no annotaion found
    throw new RuntimeException("Annotation @Restricted not found at method " 
        + m.getName() + " or it's class.");
  }
}

beans.xml位于WEB-INF文件夹中,看起来像

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       bean-discovery-mode="annotated">
    <interceptors>
        <class>ru.edu.pgtk.weducation.interceptors.LogInterceptor</class>
        <class>ru.edu.pgtk.weducation.interceptors.SecurityInterceptor</class>
    </interceptors>
</beans>

有人可以帮助我知道:

  1. 如何让拦截器在单元测试中工作?
  2. 如何在单元测试中启动授权会话(例如以管理员身份登录)?
  3. 如何使用不同的测试来测试创建和删除帐户等操作(一个测试用于创建,一个用于删除)?这是正确的 - 在一次测试中测试所有操作吗?
  4. 感谢您的时间和问题。

0 个答案:

没有答案