Package br.com.caelum.vraptor.ioc

Source Code of br.com.caelum.vraptor.ioc.GenericContainerTest$MyAppComponent

/***
* Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
* All rights reserved.
*
* 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 br.com.caelum.vraptor.ioc;

import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
import java.util.Collections;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Named;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.hamcrest.Matcher;
import org.hamcrest.MatcherAssert;
import org.joda.time.LocalDate;
import org.joda.time.LocalTime;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import br.com.caelum.vraptor.ComponentRegistry;
import br.com.caelum.vraptor.Converter;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.converter.jodatime.LocalDateConverter;
import br.com.caelum.vraptor.converter.jodatime.LocalTimeConverter;
import br.com.caelum.vraptor.core.BaseComponents;
import br.com.caelum.vraptor.core.Converters;
import br.com.caelum.vraptor.core.Execution;
import br.com.caelum.vraptor.core.MethodInfo;
import br.com.caelum.vraptor.core.RequestInfo;
import br.com.caelum.vraptor.deserialization.Deserializer;
import br.com.caelum.vraptor.deserialization.Deserializers;
import br.com.caelum.vraptor.http.route.Route;
import br.com.caelum.vraptor.http.route.Router;
import br.com.caelum.vraptor.interceptor.InterceptorRegistry;
import br.com.caelum.vraptor.ioc.fixture.ComponentFactoryInTheClasspath;
import br.com.caelum.vraptor.ioc.fixture.ComponentFactoryInTheClasspath.Provided;
import br.com.caelum.vraptor.ioc.fixture.ConverterInTheClasspath;
import br.com.caelum.vraptor.ioc.fixture.CustomComponentInTheClasspath;
import br.com.caelum.vraptor.ioc.fixture.CustomComponentWithLifecycleInTheClasspath;
import br.com.caelum.vraptor.ioc.fixture.DependentOnSomethingFromComponentFactory;
import br.com.caelum.vraptor.ioc.fixture.InterceptorInTheClasspath;
import br.com.caelum.vraptor.ioc.fixture.ResourceInTheClasspath;
import br.com.caelum.vraptor.resource.ResourceMethod;
import br.com.caelum.vraptor.scan.ScannotationComponentScannerTest;

import com.google.common.base.Objects;

import static br.com.caelum.vraptor.VRaptorMatchers.canHandle;
import static br.com.caelum.vraptor.VRaptorMatchers.hasOneCopyOf;
import static br.com.caelum.vraptor.config.BasicConfiguration.BASE_PACKAGES_PARAMETER_NAME;
import static br.com.caelum.vraptor.config.BasicConfiguration.SCANNING_PARAM;
import static java.lang.Thread.currentThread;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.sameInstance;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
* Acceptance test that checks if the container is capable of giving all
* required components.
*
* @author Guilherme Silveira
*/
public abstract class GenericContainerTest {

  protected ContainerProvider provider;
  protected ServletContext context;
  protected abstract ContainerProvider getProvider();
  protected abstract <T> T executeInsideRequest(WhatToDo<T> execution);
  protected abstract void configureExpectations();
 

  @Test
  public void canProvideAllApplicationScopedComponents() {
    checkAvailabilityFor(true, BaseComponents.getApplicationScoped().keySet());
  }

  @Test
  public void canProvideAllPrototypeScopedComponents() {
    checkAvailabilityFor(false, BaseComponents.getPrototypeScoped().keySet());
  }

  @Test
  public void canProvideAllRequestScopedComponents() {
    checkAvailabilityFor(false, BaseComponents.getRequestScoped().keySet());
  }

  @ApplicationScoped
  public static class MyAppComponent {

  }

  @Test
  public void processesCorrectlyAppBasedComponents() {
    checkAvailabilityFor(true, MyAppComponent.class, MyAppComponent.class);
  }
  @Test
  public void canProvideJodaTimeConverters() {
    executeInsideRequest(new WhatToDo<String>() {

      public String execute(RequestInfo request, int counter) {
        assertNotNull(getFromContainerInCurrentThread(LocalDateConverter.class, request));
        assertNotNull(getFromContainerInCurrentThread(LocalTimeConverter.class, request));

        Converters converters = getFromContainerInCurrentThread(Converters.class, request);
        assertTrue(converters.existsFor(LocalDate.class));
        assertTrue(converters.existsFor(LocalTime.class));
        return null;
      }

    });
  }

  @ApplicationScoped
  public static class MyAppComponentWithLifecycle {
    private int calls = 0;

    public int getCalls() {
      return calls;
    }
   
    @PreDestroy
    public void z() {
      calls++;
    }
  }

  @Test
  public void callsPredestroyExactlyOneTime() throws Exception {
    MyAppComponentWithLifecycle component = registerAndGetFromContainer(MyAppComponentWithLifecycle.class,
        MyAppComponentWithLifecycle.class);
    assertThat(component.calls, is(0));
    provider.stop();
    assertThat(component.calls, is(1));
    provider = getProvider();
    start(provider);
  }

  @Test
  public void setsAnAttributeOnRequestWithTheObjectTypeName() throws Exception {
    executeInsideRequest(new WhatToDo<Void>() {
      public Void execute(final RequestInfo request, int counter) {
        return provider.provideForRequest(request, new Execution<Void>() {

          public Void insideRequest(Container container) {
            Result result = container.instanceFor(Result.class);
            HttpServletRequest request = container.instanceFor(HttpServletRequest.class);
            assertSame(result, Objects.firstNonNull(request.getAttribute("result"), request.getAttribute("defaultResult")));
            return null;
          }
        });
      }
    });
  }

  @Test
  public void setsAnAttributeOnSessionWithTheObjectTypeName() throws Exception {
    registerAndGetFromContainer(MySessionComponent.class, MySessionComponent.class);
    executeInsideRequest(new WhatToDo<Void>() {
      public Void execute(final RequestInfo request, int counter) {
        return provider.provideForRequest(request, new Execution<Void>() {

          public Void insideRequest(Container container) {
            HttpSession session = container.instanceFor(HttpSession.class);
            MySessionComponent component = container.instanceFor(MySessionComponent.class);
            assertNotNull(component);
            assertSame(component, session.getAttribute("mySessionComponent"));
            return null;
          }
        });
      }
    });
  }

  @Component
  @RequestScoped
  @Named("teste")
  public static class MyRequestComponent {

  }

  @Test
  public void processesCorrectlyRequestBasedComponents() {
    checkAvailabilityFor(false, MyRequestComponent.class, MyRequestComponent.class);
  }

  @Component
  @PrototypeScoped
  public static class MyPrototypeComponent {

  }

  @Test
  public void processesCorrectlyPrototypeBasedComponents() {
    registerAndGetFromContainer(MyPrototypeComponent.class, MyPrototypeComponent.class);
    executeInsideRequest(new WhatToDo<Object>() {
      public Object execute(RequestInfo request, int counter) {
        return provider.provideForRequest(request, new Execution<Object>() {
          public Object insideRequest(Container container) {
            ComponentRegistry registry = container.instanceFor(ComponentRegistry.class);
            registry.register(MyPrototypeComponent.class, MyPrototypeComponent.class);

            MyPrototypeComponent instance1 = instanceFor(MyPrototypeComponent.class,container);
            MyPrototypeComponent instance2 = instanceFor(MyPrototypeComponent.class,container);
            assertThat(instance1, not(sameInstance(instance2)));
            return null;
          }
        });
      }
    });
  }

  @Test
  public void supportsComponentFactoriesForCustomInstantiation() {
    // TODO the registered component is only available in the next request
    // with Pico. FIX IT!
    registerAndGetFromContainer(Container.class, TheComponentFactory.class);

    TheComponentFactory factory = registerAndGetFromContainer(TheComponentFactory.class, null);
    assertThat(factory, is(notNullValue()));

    NeedsCustomInstantiation component = registerAndGetFromContainer(NeedsCustomInstantiation.class, null);
    assertThat(component, is(notNullValue()));

    registerAndGetFromContainer(DependentOnSomethingFromComponentFactory.class,
        DependentOnSomethingFromComponentFactory.class);

    DependentOnSomethingFromComponentFactory dependent = registerAndGetFromContainer(
        DependentOnSomethingFromComponentFactory.class, null);
    assertThat(dependent, is(notNullValue()));
    assertThat(dependent.getDependency(), is(notNullValue()));
  }

  @Before
  public void setup() throws Exception {
    context = mock(ServletContext.class, "servlet context");

    when(context.getMajorVersion()).thenReturn(3);
    when(context.getInitParameter(BASE_PACKAGES_PARAMETER_NAME)).thenReturn("br.com.caelum.vraptor.ioc.fixture");
    when(context.getRealPath("/WEB-INF/classes")).thenReturn(getClassDir());

    when(context.getClassLoader()).thenReturn(
        new URLClassLoader(new URL[] {ScannotationComponentScannerTest.class.getResource("/test-fixture.jar")},
            currentThread().getContextClassLoader()));

  //allowing(context).getInitParameter(ENCODING);
  //allowing(context).setAttribute(with(any(String.class)), with(any(Object.class)));

  when(context.getInitParameter(SCANNING_PARAM)).thenReturn("enabled");

    configureExpectations();
    provider = getProvider();
    start(provider);
  }
  protected void start(ContainerProvider provider) {
    provider.start(context);
  }

  @After
  public void tearDown() {
    provider.stop();
    provider = null;
  }

  protected <T> void checkAvailabilityFor(final boolean shouldBeTheSame, final Class<T> component,
      final Class<? super T> componentToRegister) {

    T firstInstance = registerAndGetFromContainer(component, componentToRegister);
    T secondInstance = executeInsideRequest(new WhatToDo<T>() {
      public T execute(RequestInfo request, final int counter) {
        return provider.provideForRequest(request, new Execution<T>() {
          public T insideRequest(Container secondContainer) {
            if (componentToRegister != null && !isAppScoped(secondContainer, componentToRegister)) {
              ComponentRegistry registry = secondContainer.instanceFor(ComponentRegistry.class);
              registry.register(componentToRegister, componentToRegister);
            }

            ResourceMethod secondMethod = mock(ResourceMethod.class, "rm" + counter);
            secondContainer.instanceFor(MethodInfo.class).setResourceMethod(secondMethod);
            return instanceFor(component, secondContainer);
          }
        });

      }
    });

    checkSimilarity(component, shouldBeTheSame, firstInstance, secondInstance);
  }

  protected <T> T registerAndGetFromContainer(final Class<T> componentToBeRetrieved,
      final Class<?> componentToRegister) {
    return executeInsideRequest(new WhatToDo<T>() {
      public T execute(RequestInfo request, final int counter) {

        return provider.provideForRequest(request, new Execution<T>() {
          public T insideRequest(Container firstContainer) {
            if (componentToRegister != null) {
              ComponentRegistry registry = firstContainer.instanceFor(ComponentRegistry.class);
              registry.register(componentToRegister, componentToRegister);
            }
            ResourceMethod firstMethod = mock(ResourceMethod.class, "rm" + counter);
            firstContainer.instanceFor(MethodInfo.class).setResourceMethod(firstMethod);
            return instanceFor(componentToBeRetrieved,firstContainer);
          }
        });

      }
    });
  }

  protected <T> T getFromContainer(final Class<T> componentToBeRetrieved) {
    return executeInsideRequest(new WhatToDo<T>() {
      public T execute(RequestInfo request, final int counter) {
        return getFromContainerInCurrentThread(componentToBeRetrieved, request);
      }
    });
  }
 
  protected <T> T getFromContainerInCurrentThread(final Class<T> componentToBeRetrieved, RequestInfo request) {
    return provider.provideForRequest(request, new Execution<T>() {
      public T insideRequest(Container firstContainer) {
        return instanceFor(componentToBeRetrieved,firstContainer);
      }
    });
  }

  private boolean isAppScoped(Container secondContainer, Class<?> componentToRegister) {
    return secondContainer.instanceFor(componentToRegister) != null;
  }

  protected void checkSimilarity(Class<?> component, boolean shouldBeTheSame, Object firstInstance,
      Object secondInstance) {

    if (shouldBeTheSame) {
      MatcherAssert.assertThat("Should be the same instance for " + component.getName(), firstInstance,
          is(equalTo(secondInstance)));
    } else {
      MatcherAssert.assertThat("Should not be the same instance for " + component.getName(), firstInstance,
          is(not(equalTo(secondInstance))));
    }
  }

  protected void checkAvailabilityFor(boolean shouldBeTheSame, Collection<Class<?>> components) {
    for (Class<?> component : components) {     
      checkAvailabilityFor(shouldBeTheSame, component, null);
    }
  }

  @Component
  @RequestScoped
  static public class DisposableComponent {
    private boolean destroyed;
    private Object dependency = new Object();
   
    public Object getDependency() {
      return dependency;
    }

    @PreDestroy
    public void preDestroy() {
      this.destroyed = true;
    }
   
    public boolean isDestroyed() {
      return destroyed;
    }
  }

  @Component
  static public class StartableComponent {
    private boolean started;

    @PostConstruct
    public void postConstruct() {
      this.started = true;
    }
  }

  @Test
  public void shouldDisposeAfterRequest() {
    registerAndGetFromContainer(Container.class, DisposableComponent.class);
    DisposableComponent comp = registerAndGetFromContainer(DisposableComponent.class, null);
    assertTrue(comp.destroyed);
  }

  @Test
  public void shouldStartBeforeRequestExecution() {
    registerAndGetFromContainer(Container.class, StartableComponent.class);
    StartableComponent comp = registerAndGetFromContainer(StartableComponent.class, null);
    assertTrue(comp.started);
  }

  @Test
  public void canProvideComponentsInTheClasspath() throws Exception {
    checkAvailabilityFor(false, Collections.<Class<?>> singleton(CustomComponentInTheClasspath.class));
  }

  @Test
  public void shoudRegisterResourcesInRouter() {
    Router router = getFromContainer(Router.class);
    Matcher<Iterable<? super Route>> hasItem = hasItem(canHandle(ResourceInTheClasspath.class,
        ResourceInTheClasspath.class.getDeclaredMethods()[0]));
    assertThat(router.allRoutes(), hasItem);
  }

  @Test
  public void shoudUseComponentFactoriesInTheClasspath() {
    Provided object = getFromContainer(Provided.class);
    assertThat(object, is(sameInstance(ComponentFactoryInTheClasspath.PROVIDED)));
  }
     
  @Test
  public void shoudRegisterConvertersInConverters() {
    executeInsideRequest(new WhatToDo<Converters>() {
      public Converters execute(RequestInfo request, final int counter) {
        return provider.provideForRequest(request, new Execution<Converters>() {
          public Converters insideRequest(Container container) {
            Converters converters = container.instanceFor(Converters.class);
            Converter<?> converter = converters.to(Void.class);
            assertThat(converter, is(instanceOf(ConverterInTheClasspath.class)));
            return null;
          }
        });
      }
    });
 
 
  /**
   * Check if exist {@link Deserializer} registered in VRaptor for determined Content-Types.
   */
  @Test
  public void shouldReturnAllDefaultDeserializers() {
    executeInsideRequest(new WhatToDo<Void>(){

      public Void execute(RequestInfo request, int counter) {
        return provider.provideForRequest(request, new Execution<Void>() {

          public Void insideRequest(Container container) {
            Deserializers deserializers = container.instanceFor(Deserializers.class);
            assertNotNull(deserializers.deserializerFor("application/json", container));
            assertNotNull(deserializers.deserializerFor("json", container));
            assertNotNull(deserializers.deserializerFor("application/xml", container));
            assertNotNull(deserializers.deserializerFor("xml", container));
            assertNotNull(deserializers.deserializerFor("text/xml", container));
            assertNotNull(deserializers.deserializerFor("application/x-www-form-urlencoded", container));
            return null;
          }

        });
      }
    });
 
 
  @Test
  public void shoudRegisterInterceptorsInInterceptorRegistry() {
    InterceptorRegistry registry = getFromContainer(InterceptorRegistry.class);
    assertThat(registry.all(), hasOneCopyOf(InterceptorInTheClasspath.class));
 
   
 
 
  @Test
  public void shoudCallPredestroyExactlyOneTimeForComponentsScannedFromTheClasspath() {
    CustomComponentWithLifecycleInTheClasspath component = getFromContainer(CustomComponentWithLifecycleInTheClasspath.class);
    assertThat(component.getCallsToPreDestroy(), is(equalTo(0)));
    provider.stop();
    assertThat(component.getCallsToPreDestroy(), is(equalTo(1)));

    resetProvider();
  }
 
 
 
  @Test
  public void shoudCallPredestroyExactlyOneTimeForComponentFactoriesScannedFromTheClasspath() {
    ComponentFactoryInTheClasspath componentFactory = getFromContainer(ComponentFactoryInTheClasspath.class);
    assertThat(componentFactory.getCallsToPreDestroy(), is(equalTo(0)));
    provider.stop();
    assertThat(componentFactory.getCallsToPreDestroy(), is(equalTo(1)));

    resetProvider();
  }




  protected void resetProvider() {
    provider = getProvider();
    start(provider);
  }

  protected String getClassDir() {
    return getClass().getResource("/br/com/caelum/vraptor/test").getFile();
  }
 
  protected <T> T instanceFor(final Class<T> component,
      Container secondContainer) {
    return secondContainer.instanceFor(component);
  }

}
TOP

Related Classes of br.com.caelum.vraptor.ioc.GenericContainerTest$MyAppComponent

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.