Package com.google.inject.testing.guiceberry.junit3

Source Code of com.google.inject.testing.guiceberry.junit3.GuiceBerryJunit3

/*
* Copyright (C) 2008 Google Inc.
*
* 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 com.google.inject.testing.guiceberry.junit3;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.testing.TearDown;
import com.google.common.testing.TearDownAccepter;
import com.google.guiceberry.DeprecatedGuiceBerryModule;
import com.google.guiceberry.GuiceBerry;
import com.google.guiceberry.GuiceBerry.GuiceBerryWrapper;
import com.google.guiceberry.TestDescription;
import com.google.inject.Guice;
import com.google.inject.Provider;
import com.google.inject.testing.guiceberry.GuiceBerryEnv;
import com.google.inject.testing.guiceberry.NoOpTestScopeListener;
import com.google.inject.testing.guiceberry.TestScopeListener;

import junit.framework.TestCase;

/**
* Provides the tools to manage the JUnit tests that use {@code Guice}. 
* <p>
* To use the {@link GuiceBerryJunit3} it is necessary to:
* <ul><li>
* Define a {@code Class<? extends Module>}  that specifies the appropriate bindings.
* <li>
* Annotate all the JUnit tests that use those bindings with {@link GuiceBerryEnv}
* annotation  and set the value of this annotation to the name of the module.
* <li>
* Call the {@link GuiceBerryJunit3#setUp(TestCase)} within the
* {@link TestCase#setUp()} method.
* <li>
* It is possible to define more than one module and different subclasses of
* {@link TestCase} may use the different modules (but don't have to).
* </ul>
* <p>
*  GuiceBerry is thread-safe so tests can be run in parallel.
*
* @see Guice
*
* @author Luiz-Otavio Zorzella
* @author Danka Karwanska
*/
public class GuiceBerryJunit3 {
 
  final GuiceBerry guiceBerry;

  @VisibleForTesting
  public GuiceBerryJunit3(GuiceBerry guiceBerry) {
    this.guiceBerry = guiceBerry;
  }

  private static TestDescription buildDescription(TestCase testCase) {
    return new TestDescription(
      testCase,
      testCase.getClass().getName() + "." + testCase.getName());
  }

  private static final ThreadLocal<TearDown> scaffoldingThreadLocal =
    new ThreadLocal<TearDown>();
 
  private static final GuiceBerryJunit3 INSTANCE = new GuiceBerryJunit3(GuiceBerry.INSTANCE);
 
  /**
   * Sets up the {@link TestCase} (given as the argument) to be ready to run.
   * <p>
   * The {@link TestCase} given as the argument needs to be annotated with the
   * {@link GuiceBerryEnv} annotation that provides the name of the
   * {@code Class<? extends Module>} which specifies all the injected values
   * used in this {@link TestCase}. It's necessary to add a binding that
   * binds {@link TestScopeListener} to an instance of the class that
   * implements this interface. If there is no such a {@link TestScopeListener}
   * it is possible to bind it to an instance of {@link NoOpTestScopeListener}.
   * It is also necessary to install the {@link BasicJunit3Module}
   *
   * <p>
   * Operations performed by this method include:
   * <ul>
   *    <li> If the {@link TestCase} is the instance of
   *         {@link com.google.common.testing.junit3.TearDownTestCase},
   *         the test case's {@code tearDown()} method is guaranteed to be executed
   *         at the end of the test.
   *         Otherwise  calling {@link GuiceBerryJunit3#tearDown(TestCase)} is programmer's
   *         responsibility.
   *    <li> Gets the module from the class name provided by the
   *         {@link GuiceBerryEnv} annotation  and injects the bindings specified by
   *         the module into the {@link TestCase}. It also binds {@link com.google.guiceberry.TestId}
   *         and {@link TestCase} to the corresponding {@link Provider} in the scope 
   *         defined by {@link com.google.guiceberry.TestScoped} annotation.
   *    <li> Notifies {@link TestScopeListener} that the test enters it's scope.
   *               
   *            
   * </ul>
   * <p>
   * It also starts storing the information that {@link TestCase} (given as the
   * argument) is being run.
   *
   * <p>
   * Note that you must call {@link #tearDown} if you call this method, unless
   * you're calling it from a subclass of {@link TearDownAccepter} in which case
   * it will be taken care of.
   *
   *
   * @param testCase The subclass of {@link TestCase} for which the
   *     {@link GuiceBerryJunit3#setUp} is needed.
   * @throws IllegalArgumentException If the {@link TestCase} provided  as
   *     an argument  has no {@link GuiceBerryEnv} annotation or the module
   *     provided by this annotation does not exist or {@link TestCase} is not
   *     a type of {@code Class <? extends Module>}.
   * @throws RuntimeException If the previous test has not been finished
   *     properly or it cannot create the instance of
   *     {@code Class <? extends Module>} (For example: module doesn't have no
   *     argument constructor). Also if there is a problem with injecting all
   *     the bindings or the {@link TestScopeListener} isn't binded to anything.
   *                                           
   * @see TestScopeListener
   * @see com.google.guiceberry.TestId
   * @see com.google.guiceberry.TestScoped
   * @see GuiceBerryEnv                                     
   */
  public synchronized static void setUp(final TestCase testCase) {
    INSTANCE.doSetUp(testCase);
  }

  public synchronized void doSetUp(final TestCase testCase) {
   
    TestDescription testDescription = buildDescription(testCase);

    final GuiceBerryWrapper wrapper = guiceBerry.buildWrapper(testDescription,
        new VersionTwoBackwardsCompatibleGuiceBerryEnvSelector());

    //add a tear down before setting up so that if an exception is thrown there,
    //we still do the tear down.
    maybeAddGuiceBerryTearDown(testDescription, new TearDown() {
     
      public void tearDown() throws Exception {
        wrapper.runAfterTest();
      }
    });
   
    wrapper.runBeforeTest();
  }

  private static void maybeAddGuiceBerryTearDown(
      final TestDescription testDescription,
      final TearDown toTearDown) {
    DeprecatedGuiceBerryModule.maybeAddGuiceBerryTearDown(
        scaffoldingThreadLocal, testDescription, toTearDown);
  }
 
  /**  
   * You should only call this method if your test does <em>not</em> implement
   * {@link TearDownAccepter}.
   *
   * <p>Stops storing the information that {@link TestCase} (given as the argument)
   * is being run.
   *
   * <p>Notifies {@link  TestScopeListener} corresponding to this module (
   * The {@link GuiceBerryEnv} annotation of the test case provides the name 
   * of the module)that {@link TestCase} has just become out of scope.
   * It also causes that {@link TestCase} is removed from the {@code TestScope}
   * assigned to this  module.
   *
   * <p>Do not change the value (if any) of the
   * {@link GuiceBerryEnvRemapper#GUICE_BERRY_ENV_REMAPPER_PROPERTY_NAME}
   * property, as it will likely cause the wrong {@link GuiceBerryEnv} to be
   * used on your tearDown.
   *
   * <p>If your code, for whatever reason, happens to synchronize on the test
   * class while calling the {@link #setUp(TestCase)} method, <em>and</em> you
   * run your tests in parallel, you should likewise synchronize the
   * {@link #tearDown(TestCase)}.
   *
   * @throws IllegalArgumentException If the {@link TestCase} provided  as an
   *     argument  has no {@link GuiceBerryEnv} annotation or the module
   *     provided by this annotation does not exist or {@link TestCase} is not
   *     a type of {@code Class <? extends Module>}.  
   * @throws RuntimeException If the method {@link GuiceBerryJunit3#setUp(TestCase)}
   *     wasn't called before calling this method.                                
   *
   * @see TestScopeListener
   * @see com.google.guiceberry.TestScoped
   */
  public synchronized static void tearDown(TestCase testCase) {
    if (testCase instanceof TearDownAccepter) {
      throw new UnsupportedOperationException("You must not call " +
          "GuiceBerryJunit3.tearDown (it's only needed for tests that do " +
          "not implement TearDownAccepter).");
    }
    try {
      scaffoldingThreadLocal.get().tearDown();
    } catch (Exception e) {
      throw new RuntimeException(e);
    } finally {
      scaffoldingThreadLocal.remove();
    }
  }
}
TOP

Related Classes of com.google.inject.testing.guiceberry.junit3.GuiceBerryJunit3

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.