Skip to content

Commit

Permalink
Introduce mock injection services
Browse files Browse the repository at this point in the history
- resolves weld#18
  • Loading branch information
mkouba committed Dec 16, 2017
1 parent a3de825 commit 7e42d1a
Show file tree
Hide file tree
Showing 20 changed files with 1,571 additions and 99 deletions.
39 changes: 24 additions & 15 deletions junit-common/pom.xml
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-junit-parent</artifactId>
<version>1.2.0-SNAPSHOT</version>
</parent>
<artifactId>weld-junit-common</artifactId>
<packaging>jar</packaging>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-junit-parent</artifactId>
<version>1.2.0-SNAPSHOT</version>
</parent>

<dependencies>
<dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se-core</artifactId>
</dependency>
</dependencies>
<artifactId>weld-junit-common</artifactId>
<packaging>jar</packaging>

<dependencies>

<dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se-core</artifactId>
</dependency>

<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
</dependency>

</dependencies>
</project>

Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,15 @@
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

import javax.annotation.Resource;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.context.NormalScope;
Expand All @@ -35,6 +39,7 @@
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.enterprise.util.TypeLiteral;

Expand All @@ -60,8 +65,7 @@ public abstract class AbstractWeldInitiator implements Instance<Object>, Contain
* @return a new {@link Weld} instance suitable for testing
*/
public static Weld createWeld() {
return new Weld().disableDiscovery().property(ConfigurationKey.CONCURRENT_DEPLOYMENT.get(),
false);
return new Weld().disableDiscovery().property(ConfigurationKey.CONCURRENT_DEPLOYMENT.get(), false);
}

protected final Weld weld;
Expand All @@ -74,10 +78,18 @@ public static Weld createWeld() {

protected final WeldCDIExtension extension;

private final Map<String, Object> resources;

private final Function<InjectionPoint, Object> ejbFactory;

private final Function<InjectionPoint, Object> persistenceUnitFactory;

private final Function<InjectionPoint, Object> persistenceContextFactory;

protected volatile WeldContainer container;

protected AbstractWeldInitiator(Weld weld, List<Object> instancesToInject,
Set<Class<? extends Annotation>> scopesToActivate, Set<Bean<?>> beans) {
protected AbstractWeldInitiator(Weld weld, List<Object> instancesToInject, Set<Class<? extends Annotation>> scopesToActivate, Set<Bean<?>> beans,
Map<String, Object> resources, Function<InjectionPoint, Object> ejbFactory, Function<InjectionPoint, Object> persistenceUnitFactory, Function<InjectionPoint, Object> persistenceContextFactory) {
this.instancesToInject = new ArrayList<>();
for (Object instance : instancesToInject) {
this.instancesToInject.add(createToInject(instance));
Expand All @@ -91,6 +103,10 @@ protected AbstractWeldInitiator(Weld weld, List<Object> instancesToInject,
} else {
this.extension = null;
}
this.resources = resources;
this.ejbFactory = ejbFactory;
this.persistenceContextFactory = persistenceContextFactory;
this.persistenceUnitFactory = persistenceUnitFactory;
}

protected ToInject createToInject(Object instanceToInject) {
Expand Down Expand Up @@ -183,8 +199,7 @@ public void shutdown() {

/**
*
* @return <code>true</code> if the container was initialized completely and is not shut down yet, <code>false</code>
* otherwise
* @return <code>true</code> if the container was initialized completely and is not shut down yet, <code>false</code> otherwise
*/
public boolean isRunning() {
return container.isRunning();
Expand Down Expand Up @@ -245,8 +260,7 @@ void inject() {
CreationalContext<Object> ctx = beanManager.createCreationalContext(null);
@SuppressWarnings("unchecked")
InjectionTarget<Object> injectionTarget = (InjectionTarget<Object>) beanManager
.getInjectionTargetFactory(beanManager.createAnnotatedType(instance.getClass()))
.createInjectionTarget(null);
.getInjectionTargetFactory(beanManager.createAnnotatedType(instance.getClass())).createInjectionTarget(null);
injectionTarget.inject(instance, ctx);
creationalContext = ctx;
}
Expand All @@ -269,11 +283,20 @@ protected static abstract class AbstractBuilder<I extends AbstractWeldInitiator,

protected final Set<Bean<?>> beans;

protected final Map<String, Object> resources;

protected Function<InjectionPoint, Object> ejbFactory;

protected Function<InjectionPoint, Object> persistenceUnitFactory;

protected Function<InjectionPoint, Object> persistenceContextFactory;

public AbstractBuilder(Weld weld) {
this.weld = weld;
this.instancesToInject = new ArrayList<>();
this.scopesToActivate = new HashSet<>();
this.beans = new HashSet<>();
this.resources = new HashMap<>();
}

/**
Expand All @@ -292,17 +315,15 @@ public final T activate(Class<? extends Annotation>... normalScopes) {
continue;
}
if (!scope.isAnnotationPresent(NormalScope.class)) {
throw new IllegalArgumentException(
"Only annotations annotated with @NormalScope are supported!");
throw new IllegalArgumentException("Only annotations annotated with @NormalScope are supported!");
}
this.scopesToActivate.add(scope);
}
return self();
}

/**
* Instructs the initiator to inject the given non-contextual instance once the container is started, i.e.
* during test execution.
* Instructs the initiator to inject the given non-contextual instance once the container is started, i.e. during test execution.
*
* <p>
* This method could be used e.g. to inject a test class instance:
Expand All @@ -325,9 +346,8 @@ public final T activate(Class<? extends Annotation>... normalScopes) {
* </pre>
*
* <p>
* Injected {@link Dependent} bean instances are destroyed after the test execution. However, the licecycle of the
* non-contextual instance is not managed by the container and all injected references will be invalid after the test
* execution.
* Injected {@link Dependent} bean instances are destroyed after the test execution. However, the licecycle of the non-contextual instance is not
* managed by the container and all injected references will be invalid after the test execution.
* </p>
*
* @param instance
Expand All @@ -351,10 +371,71 @@ public T addBeans(Bean<?>... beans) {
return self();
}

/**
* Binds a name to an object. This allows to mock {@link Resource} injection points easily, e.g.:
*
* <pre>
* &#64;Dependent
* class Foo {
*
* &#64;Resource(lookup = "bar")
* String bar;
* }
* </pre>
*
* @param name
* @param resource
* @return self
* @since 1.2
*/
public T bindResource(String name, Object resource) {
resources.put(name, resource);
return self();
}

/**
* Makes it possible to mock {@code @EJB} injection points.
*
* <p>
* Note that for Weld 3 {@code org.jboss.weld.module:weld-ejb} dependency is also required.
* </p>
*
* @param ejbFactory
* @return self
* @since 1.2
*/
public T setEjbFactory(Function<InjectionPoint, Object> ejbFactory) {
this.ejbFactory = ejbFactory;
return self();
}

/**
* Makes it possible to mock {@code PersistenceUnit} injection points.
*
* @param persistenceUnitFactory
* @return self
* @since 1.2
*/
public T setPersistenceUnitFactory(Function<InjectionPoint, Object> persistenceUnitFactory) {
this.persistenceUnitFactory = persistenceUnitFactory;
return self();
}

/**
* Makes it possible to mock {@code PersistenceContext} injection points.
*
* @param persistenceContextFactory
* @return self
* @since 1.2
*/
public T setPersistenceContextFactory(Function<InjectionPoint, Object> persistenceContextFactory) {
this.persistenceContextFactory = persistenceContextFactory;
return self();
}

protected abstract T self();

protected abstract I build(Weld weld, List<Object> instancesToInject,
Set<Class<? extends Annotation>> scopesToActivate, Set<Bean<?>> beans);
protected abstract I build(Weld weld, List<Object> instancesToInject, Set<Class<? extends Annotation>> scopesToActivate, Set<Bean<?>> beans);

/**
*
Expand All @@ -369,6 +450,17 @@ public I build() {
}

protected WeldContainer initWeldContainer(Weld weld) {
// Register mock injection services if needed
if (!resources.isEmpty()) {
weld.addServices(new MockResourceInjectionServices(resources));
}
if (ejbFactory != null) {
weld.addServices(new MockEjbInjectionServices(ejbFactory));
}
if (persistenceContextFactory != null || persistenceUnitFactory != null) {
weld.addServices(new MockJpaInjectionServices(persistenceUnitFactory, persistenceContextFactory));
}
// Init the container
container = weld.initialize();
injectInstances();
if (extension != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2017, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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 org.jboss.weld.junit;

import java.util.function.Function;

import javax.enterprise.inject.spi.InjectionPoint;

import org.jboss.weld.injection.spi.EjbInjectionServices;
import org.jboss.weld.injection.spi.ResourceReference;
import org.jboss.weld.injection.spi.ResourceReferenceFactory;
import org.jboss.weld.injection.spi.helpers.SimpleResourceReference;
import org.jboss.weld.junit.AbstractWeldInitiator.AbstractBuilder;

/**
*
* @author Martin Kouba
* @see AbstractBuilder#setEjbFactory(Function)
*/
public class MockEjbInjectionServices implements EjbInjectionServices {

private final Function<InjectionPoint, Object> ejbFactory;

public MockEjbInjectionServices(Function<InjectionPoint, Object> ejbFactory) {
this.ejbFactory = ejbFactory;
}

@Override
public void cleanup() {
}

@Override
public ResourceReferenceFactory<Object> registerEjbInjectionPoint(InjectionPoint injectionPoint) {
return new ResourceReferenceFactory<Object>() {
@Override
public ResourceReference<Object> createResource() {
return new SimpleResourceReference<Object>(resolveEjb(injectionPoint));
}
};
}

@Override
public Object resolveEjb(InjectionPoint injectionPoint) {
return ejbFactory.apply(injectionPoint);
}

}
Loading

0 comments on commit 7e42d1a

Please sign in to comment.