2 Replies Latest reply on Oct 29, 2008 5:30 PM by Olivier Thierry

    Authentication and unit tests

    Olivier Thierry Apprentice

      Hi,


      I try to write a unit test for a Seam component in which I inject org.jboss.seam.security.identity component. Actually this component uses identity.getCredentials().getUserName() method. But I can't see an easy way to authenticate when running unit tests. I mean I don't want to have to setup an authentication manager or something like that, I just need to have identity component instantiated with credentials set. How should I do this ?


      Thanks in advance,


      Olivier

        • 1. Re: Authentication and unit tests
          Olivier Thierry Apprentice

          I still try to make it work but I can't find the way to do it. Drawing on org.jboss.seam.test.integration.security.SecurityTest, I wrote a mock identity component which uses MockLoginModule bundled with Seam.



          @Name("org.jboss.seam.security.identity")
          @Install(precedence = Install.MOCK)
          @Scope(ScopeType.SESSION)
          @BypassInterceptors
          @Startup
          public class MockIdentity extends Identity {
          
              private Configuration createMockJAASConfiguration() {
                  return new Configuration() {
                   private AppConfigurationEntry[] aces = { new AppConfigurationEntry(
                       MockLoginModule.class.getName(),
                    LoginModuleControlFlag.REQUIRED,
                    new HashMap<String, String>()) };
          
                      @Override
                   public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
                       return aces;
                   }
          
                   @Override
                   public void refresh() {
                   }
               };
              }
          
              @Override
              protected LoginContext getLoginContext() throws LoginException {
                  return new LoginContext("default", getSubject(), getCredentials()
                   .createCallbackHandler(), createMockJAASConfiguration());
              }
          }



          Then I wrote my test method  :


          @org.testng.annotations.Test(
          public void testSaveThenDeleteEmployee()  throws java.lang.Exception
          {
              new ComponentTest() {
               public void testComponents() throws java.lang.Exception {
                   EmployeeInternalServiceLocal service = (EmployeeInternalServiceLocal) getInstance("employeeInternalService");
                         
                       // Login
                              
                   Identity identity = (Identity) getInstance("org.jboss.seam.security.identity");
                   identity.create();
                   identity.getCredentials().setUsername("test");
                   identity.getCredentials().setPassword("test");
                   assert "loggedIn".equals(identity.login());
                   assert identity.isLoggedIn();
          
                   // Create an employee
                              
                   Employee employee = new Employee();
                   employee.setRollNumber("EMP_TEST");
                   employee.setName("Name");
                   employee.setFirstName("FirstName");
                   employee = service.saveEmployee(employee);
                   
                   assert employee.getId() != null;
                   assert employee.getCreationDate() != null;
                   assert employee.getCreationUser() != null;
                   assert employee.getCreationDate().equals(employee.getLastUpdateDate());
                   assert employee.getCreationUser().equals(employee.getLastUpdateUser());
               }               
              }.run();
          }



          In my employeeInternalService component, I inject the identity component :


          @org.jboss.seam.annotations.In("org.jboss.seam.security.identity")
          org.jboss.seam.security.Identity identity;



          And finally I use it this way :



          java.util.Date lastUpdateDate = new java.util.Date(); 
          employee.setCreationDate(lastUpdateDate);
          employee.setLastUpdateDate(lastUpdateDate);
          if (identity != null && identity.getPrincipal() != null) {
              employee.setCreationUser(identity.getPrincipal().getName());
              employee.setLastUpdateUser(identity.getPrincipal().getName());
          }
          emanager.persist(employee);
          emanager.flush();



          But I still have null value in creationUser and lastUpdateUser fields. Yet it should work with a mock identity component, doesn't it ? Did I miss something ?

          • 2. Re: Authentication and unit tests
            Olivier Thierry Apprentice

            How stupid I am ! I tried something complicated while it was so simple. I had no need of MockLoginModule, I just had to use standard SeamLoginModule and write my own very simple authenticator :


            @Name("authenticator")
            @Scope(org.jboss.seam.ScopeType.STATELESS)
            @Install(precedence=Install.MOCK)
            public class MockAuthenticator {
            
                 public boolean authenticate() {
                      return true;
                 }
                 
            }



            Then in components.xml used for my tests :


            <security:identity authenticate-method="#{authenticator.authenticate}" />



            And in my test method :



            Identity identity = Identity.instance();
            identity.getCredentials().setUsername("test");
            identity.getCredentials().setPassword("test");
            assert "loggedIn".equals(identity.login());
            


            Actually you just have to do it the standard way, no special need for unit tests ! And it took hours for me to see something so obvious lol