content: /**
   * Copyright 2014 55 Minutes (http://www.55minutes.com)
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *    http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package fiftyfive.wicket.shiro.test;
  
  import org.apache.shiro.session.Session;
  import org.apache.shiro.subject.Subject;
  import org.apache.shiro.subject.support.SubjectThreadState;
  import org.apache.shiro.util.ThreadState;
  import org.junit.After;
  import org.junit.Before;
  import org.mockito.Mockito;
  
  /**
   * Enables {@link org.apache.wicket.util.tester.WicketTester WicketTester} to be used with
   * a Shiro-enabled Wicket application by mocking
   * the Shiro infrastructure. The code is not Wicket-specific, so you can use this for testing
   * non-Wicket code as well. Just make this the base class for your JUnit tests.
   * <b>Requires JUnit 4, Mockito.</b>
   * <p>
   * During your tests, mock the authentication state like this:
   * <pre class="example">
   * // Simulate authenticated user
   * when(this.mockSubject.isAuthenticated()).thenReturn(true);
   * 
   * // Simulate absence of "admin" role
   * doThrow(new AuthorizationException()).when(this.mockSubject).checkRole("admin");</pre>
   * <p>
   * If you're not using JUnit 4 and Mockito or otherwise can't subclass this class,
   * you can implement the same technique that this class uses with the testing frameworks of your
   * choice. This class simply does the following:
   * <pre class="example">
   * // Run before every test so that SecurityUtils.getSubject() returns a mock:
   * this.mockSubject = Mockito.mock(org.apache.shiro.subject.Subject.class);
   * this.threadState = new org.apache.shiro.subject.support.SubjectThreadState(this.mockSubject);
   * this.threadState.bind();
   * 
   * // Run after every test to clear the thread local:
   * this.threadState.clear();</pre>
   * 
   * @since 3.0
   */
  public abstract class AbstractShiroJUnit4Tests
  {
      private ThreadState threadState;
      
      /**
       * The Mockito mock that will be returned by
       * {@link org.apache.shiro.SecurityUtils#getSubject() SecurityUtils.getSubject()}.
       * Use this mock in your tests to mock authentication and authorization prerequisites.
       */
      protected Subject mockSubject;
      
      /**
       * The Mockito mock that will be returned by
       * {@link Subject#getSession() SecurityUtils.getSubject().getSession()}.
       */
      protected Session mockShiroSession;
      
      /**
       * Install a Mockito mock of {@link Subject} in Shiro's thread local. This causes the mock
       * to be returned when application code (and fiftyfive-wicket-shiro code) calls
       * {@link org.apache.shiro.SecurityUtils#getSubject() SecurityUtils.getSubject()}.
       */
      @Before
      public void attachSubject()
      {
          this.mockShiroSession = Mockito.mock(Session.class);
          this.mockSubject = Mockito.mock(Subject.class);
          Mockito.when(this.mockSubject.getSession()).thenReturn(this.mockShiroSession);
          this.threadState = new SubjectThreadState(this.mockSubject);
          this.threadState.bind();
      }
      
      /**
       * Clear Shiro's thread local so that any subject mocking we've done during the test does
       * not pollute subsequent tests.
       */
      @After
      public void detachSubject()
      {
          this.threadState.clear();
      }
  }
  