Interceptors doesn't work in Unit tests

510 Views Asked by At

I am get Interceptors working on the application server. I have annotated 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);
    }
  }  
}

Empty list of roles means, that It's allowed only for role admin.

Here the unit test file for this 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());
    }
  }
}

And this test working. I think, that is not correct, because there is no user with admin role logged in. But why this behavior happing?

UPDATED.

@Restricted interface:

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

SecurityInterceptor class

@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.");
  }
}

The beans.xml is placed in WEB-INF folder and looks like

<?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>

Can someone help me to know:

  1. How to get Interceptors working in Unit tests?
  2. How to start authorized session in Unit tests (log in as admin, for example)?
  3. How to test such operations as creation and deleting account with the different tests (one test for creating, one for deleting)? Is it correct - to test all operations in one test?

Thank you for your time and your questions.

0

There are 0 best solutions below