diff --git a/junit5/pom.xml b/junit5/pom.xml index fe40592b..d6455017 100644 --- a/junit5/pom.xml +++ b/junit5/pom.xml @@ -52,10 +52,8 @@ org.jboss.weld.module weld-ejb - ${version.weld} - test - + diff --git a/junit5/src/test/java/org/jboss/weld/junit5/auto/AutoConfigWithWeldSetupTest.java b/junit5/src/test/java/org/jboss/weld/junit5/auto/AutoConfigWithWeldSetupTest.java index 4a91db9d..318c5867 100644 --- a/junit5/src/test/java/org/jboss/weld/junit5/auto/AutoConfigWithWeldSetupTest.java +++ b/junit5/src/test/java/org/jboss/weld/junit5/auto/AutoConfigWithWeldSetupTest.java @@ -21,7 +21,7 @@ * exception was throws inside an extension. The test is fragile and can break because of internal JUnit 5 changes * in which case we might want to revisit if we want to keep it or whether there is a better way. * - * @author bkautler + * @author Björn Kautler */ @EnableAutoWeld class AutoConfigWithWeldSetupTest { @@ -37,7 +37,7 @@ void test() { } /** - * @author bkautler + * @author Björn Kautler */ static public class AssertExceptionExtension implements AfterEachCallback { diff --git a/pom.xml b/pom.xml index ee5502a5..721be3f7 100644 --- a/pom.xml +++ b/pom.xml @@ -42,10 +42,16 @@ 4.13.2 5.8.2 + 2.1-groovy-3.0 + 1.8.2 + 3.0.10 5.0.0.CR2 4.4.0 4.0.0 + 2.0.1 + 4.0.0 3.1.0-RC2 + 2.17.2 4.6.0 4.6.0.0 @@ -56,6 +62,7 @@ junit4 junit5 + spock junit-common @@ -87,6 +94,25 @@ ${version.junit.jupiter} + + org.spockframework + spock-core + ${version.spock} + + + + org.junit.platform + junit-platform-testkit + ${version.junit.platform} + test + + + + org.codehaus.groovy + groovy + ${version.groovy} + + org.mockito mockito-core @@ -119,6 +145,20 @@ spotbugs-annotations ${version.spotbugs} + + + org.apache.logging.log4j + log4j-core + ${version.log4j} + test + + + + org.jboss.weld.module + weld-ejb + ${version.weld} + test + @@ -144,6 +184,7 @@ true ${spotbugs.threshold} ${spotbugs.failOnError} + ${spotbugs.excludeFilterFile} @@ -172,6 +213,32 @@ + + org.codehaus.gmavenplus + gmavenplus-plugin + 1.13.1 + + + + addTestSources + compileTests + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + https://static.javadoc.io/org.jboss.weld.se/weld-se-core/${version.weld}/ + https://static.javadoc.io/jakarta.inject/jakarta.inject-api/${version.jakarta.inject}/ + https://static.javadoc.io/jakarta.enterprise/jakarta.enterprise.cdi-api/${version.jakarta.cdi}/ + https://static.javadoc.io/org.jboss.weld.environment/weld-environment-common/${version.weld}/ + https://static.javadoc.io/org.spockframework/spock-core/${version.spock}/ + + + diff --git a/spock/.gitignore b/spock/.gitignore new file mode 100644 index 00000000..88414527 --- /dev/null +++ b/spock/.gitignore @@ -0,0 +1,6 @@ +/target/ +/.settings/ +/.classpath +/.project +/.idea +*.iml diff --git a/spock/README.md b/spock/README.md new file mode 100644 index 00000000..b3003918 --- /dev/null +++ b/spock/README.md @@ -0,0 +1,752 @@ +# Weld Spock Extension + +There is one global Spock extension in this module, the behavior of which can be configured using various annotations. +By default, the extension has no effect at all. To use the extension you either have to annotate some specification +or feature with `@EnableWeld`, or enable the processing for all specifications (unless disabled specifically) using +the Spock configuration file. + +In their default behaviour, the `@EnableWeld` annotation will cause a Weld SE container to be started and stopped +for each iteration of each feature where the extension is configured to run. The package of the specification will be +searched for beans and those added to the container. All `@Shared` and non-`@Shared` fields of the specification and +super specifications that are annotated with `@Inject` will be injected. All method parameters of all fixture and +feature methods that are no data variables and not yet provided by a different Spock extension and are resolvable +in the container are injected automatically too. + +Furthermore, you can provide explicit configuration for the Weld container, or modify the configuration in various ways +as further described below - extensions, scope activation, interception, ... + +The extension fully supports parallel execution mode of Spock, except for if `WeldContainer.current()` is used which +does not work if multiple containers are running from the same class loader. This includes the usage of +`MockBean.Builder#useUnmanaged` with the default create function and also `MockBean.read` which calls `useUnmanaged` +internally, as soon as the according beans are resolved and thus created. If either of these are used, you will +get a `WELD-ENV-002016` error if another container is running at the same time, so you should use `@Isolated` +for these features to make sure they are running individually. + +Minimum requirements are Spock 2 and Java 11. + +## Table of contents + +* [Maven Artifact](#maven-artifact) +* [Enabling and Disabling the Extension](#enabling-and-disabling-the-extension) +* [Scope of the Started Weld Container](#scope-of-the-started-weld-container) + * [Iteration Scope](#iteration-scope) + * [Feature Scope](#feature-scope) + * [Specification Scope](#specification-scope) +* [Configuration Versus Automagic](#configuration-versus-automagic) +* [The Manual Mode](#the-manual-mode) + * [WeldInitiator and @WeldSetup](#weldinitiator-and-weldsetup) + * [Convenient Starting Points](#convenient-starting-points) + * [Test Class Injection](#test-class-injection) + * [Activating Context for a Normal Scope](#activating-context-for-a-normal-scope) + * [Adding mock beans](#adding-mock-beans) + * [Adding mock interceptors](#adding-mock-interceptors) + * [Mock injection services](#mock-injection-services) +* [The Automagic Mode](#the-automagic-mode) + * [`@ActivateScopes`](#activatescopes) + * [`@AddBeanClasses`](#addbeanclasses) + * [`@AddEnabledDecorators`](#addenableddecorators) + * [`@AddEnabledInterceptors`](#addenabledinterceptors) + * [`@AddExtensions`](#addextensions) + * [`@AddPackages`](#addpackages) + * [`@EnableAlternativeStereotypes`](#enablealternativestereotypes) + * [`@EnableAlternatives`](#enablealternatives) + * [`@ExcludeBean`](#excludebean) + * [`@ExcludeBeanClasses`](#excludebeanclasses) +* [Additional Configuration](#additional-configuration) + * [Explicit Parameter Injection](#explicit-parameter-injection) + * [Flat Deployment](#flat-deployment) +* [IllegalStateException in Assertion Failure Rendering](#illegalstateexception-in-assertion-failure-rendering) + +## Maven Artifact + +```xml + + org.jboss.weld + weld-spock + ${version.weld-spock} + +``` + +## Enabling and Disabling the Extension + +If a feature has an `@EnableWeld` or `@DisableWeld` annotation applied, this is what is effective. +If Weld is disabled, no container will be started for the feature or the iterations and no non-`@Shared` fields, +or method parameters will be injected. However, if for the specification a `SPECIFICATION` scoped Weld +was booted due to annotation or Spock configuration file options, +this container will have injected instances into the `@Shared` fields already. + +If a feature has neither of the two annotations applied, the configuration of the specification is inherited. + +If a specification has an `@EnableWeld` or `@DisableWeld` annotation applied, this is effective +for all features that do not have their own annotation. It will have the same effect as if the annotation +is copied to all features that have none of the two annotations already, except if scope `SPECIFICATION` is selected, +as this is only valid in a specification level annotation or the Spock configuration file. + +If a specification has neither of the two annotations applied, the super specifications are searched in order +and if an annotated one is found, its annotation is effective as if it were on the specification directly. + +In case no annotation is found in super specifications, the settings from the Spock configuration file +or the respective default settings are effective. To enable the extension with the detail options from the configuration +file or the default on all specifications that don't have either annotation and there on all features that don't have +either, the configuration file entry looks like: +```groovy +'org.jboss.weld' { + enabled true +} +``` + +If an element is annotated with both of these annotations, an exception is thrown, +as it is unclear which should have precedence. + +If a class that is no specification or a method that is no feature is annotated with either of those annotations, +they are simply ignored and have no effect at all. + +The properties of the `@EnableWeld` annotation, the Spock configuration file options, and the additional annotations +as described below can be used to further specify the behavior of the extension. + +## Scope of the Started Weld Container + +Using the `scope` configuration file option if the global configuration is effective, or the `scope` property of the +`@EnableWeld` annotation if it is effective, the scope of the started Weld container can be configured. + +### Iteration Scope + +By default, the scope is `ITERATION`, which means that before an iteration (before the `setup` method is called) +a new Weld container will be started, exclusively used for this iteration and after the iteration +(after the `cleanup` method is called) shut down again. + +The `@Shared` fields will be injected, but only at the time the iteration starts running. If you have multiple +such Weld instances in one specification and use the parallel execution feature of Spock, those Weld containers might +overwrite each other's values, so be careful what you configure to not get unexpected results. + +The non-`@Shared` fields will also be injected, as well as method parameters of `setup`, feature, and `cleanup` methods. + +`setupSpec` and `cleanupSpec` method parameters will not be injected as at the time those methods are executed, +the Weld container is either not yet running or already shut down. + +### Feature Scope + +Before a feature (before the `setup` method of the first iteration is called) a new Weld container will be started, +exclusively used for all iterations of this feature and after the feature (after the `cleanup` method +of the last iteration is called) shut down again. + +The `@Shared` fields will be injected, but only at the time the first iteration starts running. If you have multiple +such Weld instances in one specification and use the parallel execution feature of Spock, those Weld containers might +overwrite each other's values, so be careful what you configure to not get unexpected results. + +The non-`@Shared` fields will also be injected, as well as method parameters of `setup`, feature, and `cleanup` methods. + +`setupSpec` and `cleanupSpec` method parameters will not be injected as at the time those methods are executed, +the Weld container is either not yet running or already shut down. + +### Specification Scope + +Before a specification (before the `setupSpec` method is called) a new Weld container will be started, +exclusively used for all iterations of all features of this specification and after the specification +(after the `cleanupSpec` method is called) shut down again. + +The `@Shared` fields will be injected once after the container was booted successfully. + +The non-`@Shared` fields will also be injected, as well as method parameters of feature, and all fixture methods. + +This scope can only be selected on a specification or in the Spock configuration file. +If it is used for a feature annotation, an exception will be thrown. + +_**Example:**_ +```groovy +import static org.jboss.weld.spock.EnableWeld.Scope.SPECIFICATION + +'org.jboss.weld' { + scope SPECIFICATION +} +``` + +## Configuration Versus Automagic + +The configuration file section and the `@EnableWeld` annotation have a boolean option `automagic` with which one of two +modes can be selected that ultimately achieve the same thing, but each opt for a different approach. + +By default, the value is `false` and a declarative configuration mode is chosen, much like booting Weld SE itself. There +are some additional builder patterns on top of that allowing for easy addition of mocked beans and such. The advantage +of this approach is that you have complete control over what gets into the Weld container and can easily change that. On +the other hand, it may be rather verbose and requires you to add a specifically annotated field to every specification. + +If the option is set to `true`, a more annotation based approach is used, where no special field in the specification is +necessary. In fact, often nothing except for the `@EnableWeld(automagic = true)` annotation is necessary and this +extension will do its best to find out what classes should be added to the Weld container as beans. +This of course makes some assumptions on your specifications which may not always be met, hence there is a bunch of +annotations which allow you to configure the container further. +Advantages of this approach are quick setup for basic cases, less verbose code and that eerie feeling that things +are happening automagically. On the not so bright side, automatic config is not almighty and in some cases will falter, +forcing some configuration to be done via annotations. +Last but not least, overly complex test scenarios may mean loads of annotations, and you may be better off with the +declarative approach. + +## The Manual Mode + +The simplest way to use this extension is to annotate your specification with `@EnableWeld`. +With just this annotation, the Weld container will be started before each iteration is run and stopped afterwards. + +This default behaviour includes: +* Bootstrap Weld SE container with + * Disabled discovery + * Disabled concurrent deployment + * Added specification package as source of beans +* Inject into all `@Shared` fields of the specification that are annotated with `@Inject` +* Inject into all non-`@Shared` fields of the specification that are annotated with `@Inject` +* Inject into `setup`, feature, and `cleanup` method parameters of your specification + * If the parameter is no data variable + * If no other Spock extension already provided a value for it + * If the type of the parameter matches a known and resolvable bean + * By default, Weld is greedy and will try to resolve all parameters which are known as bean types in the container + * If this behaviour should be different, refer to [additional configuration section](#explicit-parameter-injection) +* Shut down the container after iteration is done + +_**Example:**_ +```groovy +@EnableWeld +class BasicUsageTest extends Specification { + @Inject + MyBean myBean + + def 'test foo'(MyOtherBean otherBean) { + // Weld SE container is bootstrapped here and the injection points are resolved + expect: + true + } +} +``` + +### WeldInitiator and @WeldSetup + +`org.jboss.weld.spock.WeldInitiator` is the entry point with which the boostrap of Weld can be customized. +The container is configured through a provided `org.jboss.weld.environment.se.Weld` instance. +By default, the container is optimized for testing purposes, i.e. with automatic discovery and concurrent deployment +disabled (see also `WeldInitiator.createWeld()`). However, it is possible to provide a customized `Weld` instance +- see also `WeldInitiator.of(Weld)` and `WeldInitiator.from(Weld)` methods. +`WeldInitiator` also implements `Instance` and therefore might be used to perform programmatic lookup of bean instances. + +`WeldInitiator` should be available in a field annotated with `@WeldSetup`. If the scope `SPECIFICATION` is effective, +or for a data-driven feature if scope `FEATURE` is effective, `@Shared` fields of the specification and its super +specifications are searched for exactly one field that is annotated with `@WeldSetup`. + +If multiple such fields are found, an exception is thrown. + +If exactly one is found, and its value is not of type `WeldInitiator`, an exception is thrown. + +Otherwise, as the type is correct, it is used as-is to initialize the Weld container. + +From there you can use static methods. + +_**Example:**_ +```groovy +@EnableWeld +class MyNewTest extends Specification { + @WeldSetup + def weld = WeldInitiator.of(SomeClass) + + def 'test foo'() {...} +} +``` + +#### Convenient Starting Points + +A convenient static method `WeldInitiator.of(Class...)` is also provided - in this case, the container is optimized +for testing purposes and only the given bean classes are considered. + +_**Example:**_ +```groovy +@EnableWeld +class SimpleTest extends Specification { + @WeldSetup + def weld = WeldInitiator.of(Foo) + + def 'test foo'() { + // Note that Weld container is started automatically + + expect: 'WeldInitiator can be used to perform programmatic lookup of beans' + weld.select(Foo).get().baz == 'baz' + + and: 'WeldInitiator can be used to fire a CDI event' + weld.event().select(Baz).fire(new Baz()) + } +} +``` + +It's also possible to use `WeldInitiator.ofTestPackage()` - the container is optimized for testing purposes +and all the classes from the specification package are added automatically. + +_**Example:**_ +```groovy +@EnableWeld +class AnotherSimpleTest extends Specification { + @WeldSetup + def weld = WeldInitiator.ofTestPackage() + + def 'test foo'() { + expect: + // Alpha comes from the same package as AnotherSimpleTest + weld.select(Alpha).ping() == 1 + } +} +``` + +Furthermore, `WeldInitiator.Builder` can be used to customize the final `WeldInitiator` instance, +e.g. to *activate a context for a given normal scope*. + +##### Test Class Injection + +Everytime the extension is effective for a feature, it will automatically resolve all `@Inject` fields of the +specification as well as attempt to resolve fixture and feature method parameters, should they be injectable beans, +no data variables and not yet provided by another extension. + +_**Example:**_ +```groovy +@EnableWeld +class InjectTest extends Specification { + @WeldSetup + def weld = WeldInitiator.from(Foo).build() + + // Gets injected before executing test + @Inject + @MyQualifier + Foo foo + + def 'test foo'(Foo fooAsParam) { + expect: + foo.value == 42 + fooAsParam.value == 42 + } +} +``` + +##### Activating Context for a Normal Scope + +`WeldInitiator.Builder.activate(Class...)` makes it possible to activate and deactivate contexts +for the specified normal scopes for each iteration execution. + +_**Example:**_ +```groovy +@EnableWeld +class ContextsActivatedTest extends Specification { + @WeldSetup + def weld = WeldInitiator + .from(Foo, Oof) + .activate(RequestScoped, SessionScoped) + .build() + + def 'contexts for @RequestScoped and @SessionScoped should be active'() { + expect: + // Foo is @RequestScoped + weld.select(Foo).get().doSomethingImportant() + // Oof is @SessionScoped + weld.select(Oof).get().doSomethingVeryImportant() + } +} +``` + +##### Adding mock beans + +Sometimes it might be necessary to add a mock for a bean that cannot be part of the test deployment, +e.g. the original bean implementation has dependencies which cannot be satisfied in the test environment. +Very often, it's an ideal use case for the Spock build-in mocking and stubbing functionality, +i.e. to create a bean instance with the desired behavior and verify behavior. + +In this case, there are two options. +* The first option is to add a + [producer method](https://jakarta.ee/specifications/cdi/3.0/jakarta-cdi-spec-3.0.html#producer_method) + or [field](https://jakarta.ee/specifications/cdi/3.0/jakarta-cdi-spec-3.0.html#producer_field) to the specification + and add the specification as bean to the deployment. The test class will be recognized as a bean + and therefore the producer will also be discovered. + + _**Example:**_ + ```groovy + interface Bar { + String ping() + } + + class Foo { + @Inject + Bar bar + + String ping() { + bar.ping() + } + } + + @EnableWeld + class TestClassProducerTest extends Specification { + @WeldSetup + def weld = WeldInitiator.from(Foo, TestClassProducerTest).build() + + @ApplicationScoped + @Produces + Bar produceBar() { + // Stub object provided by Spock + Stub(Bar) { + ping() >> 'pong' + } + } + + def 'test foo'() { + expect: + weld.select(Foo).get().ping() == 'pong' + } + } + ``` + This should work in most of the cases (assuming the test class + [meets some conditions](https://jakarta.ee/specifications/cdi/3.0/jakarta-cdi-spec-3.0.html#what_classes_are_beans)) + although it's a little bit cumbersome. + +* The second option is `WeldInitiator.Builder.addBeans(Bean...)` which makes it possible to add beans during + `AfterBeanDiscovery` phase easily. You can provide your own `Bean` implementation or, for most use cases, + a convenient `org.jboss.weld.junit.MockBean` should be sufficient. + `MockBean.builder()` can be used to obtain a new builder instance. + +_**Example:**_ +```groovy +interface Bar { + String ping() +} + +class Foo { + @Inject + Bar bar + + String ping() { + bar.ping() + } +} + +@EnableWeld +class AddBeanTest extends Specification { + @WeldSetup + def weld = WeldInitiator.from(Foo).addBeans(createBarBean()).build() + + static createBarBean() { + MockBean + .builder() + .types(Bar) + .scope(ApplicationScoped) + .creating(Stub(Bar) { + ping() >> 'pong' + }) + .build() + } + + def 'test foo'() { + expect: + weld.select(Foo).get().ping() == 'pong' + } +} +``` + +##### Adding mock interceptors + +Sometimes it might be useful to add a mock interceptor, e.g. if an interceptor implementation requires some +environment-specific features. For this use case the `MockInterceptor` is a perfect match. + +_**Example:**_ +```groovy +@FooBinding +class Foo { + boolean ping() { + true + } +} + +@Target([TYPE, METHOD]) +@Retention(RUNTIME) +@InterceptorBinding +@interface FooBinding { + static final class Literal extends AnnotationLiteral implements FooBinding { + public static final Literal INSTANCE = new Literal() + } +} + +@EnableWeld +class MockInterceptorTest extends Specification { + @WeldSetup + def weld = WeldInitiator + .from(Foo) + .addBeans(MockInterceptor + .withBindings(FooBinding.Literal.INSTANCE) + .aroundInvoke { ctx, b -> false }) + .build() + + def 'interception should work properly'() { + expect: + !weld.select(Foo).get().ping() + } +} +``` + +##### Mock injection services + +If a bean under the test declares a non-CDI injection point (such as `@Resource`) a mock injection service must be +installed. `WeldInitiator.Builder` comes with several convenient methods which allow to easily mock the Weld SPI: + +* `bindResource()` - to handle `@Resource` +* `setEjbFactory()` - to handle `@EJB` +* `setPersistenceUnitFactory()` - to handle `@PersistenceUnit` +* `setPersistenceContextFactory()` - to handle `@PersistenceContext` + +_**Example:**_ +```groovy +class Baz { + @Resource(lookup = 'somejndiname') + String coolResource +} + +@EnableWeld +class MyTest extends Specification { + @WeldSetup + def weld = WeldInitiator + .from(Baz) + .bindResource('somejndiname', 'coolString') + .build() + + def test(Baz baz) { + expect: + baz.coolResource == 'coolString' + } +} +``` + +## The Automagic Mode + +To use this approach, the `automagic` property is set to `true`, either in the Spock configuration file if the global +settings are effective or in the `@EnableWeld` annotation if it is effective. + +By default, the extension will: +* Inspect the specification and try to figure out what bean classes it needs based on injection points + (field and parameter injection both work) + * This is done by finding classes and verifying whether they have a + [bean defining annotation](https://jakarta.ee/specifications/cdi/3.0/jakarta-cdi-spec-3.0.html#bean_defining_annotations), + so make sure they do +* Add those classes to the Weld container +* Process additional annotations on the specification and also on each discovered class + * `@AddPackages`, `@AddExtensions`, `@ActivateScopes`, ... +* Annotates specifications with `@Singleton` and prevents another instantiation by Weld, + and instead substitutes the specification instances provided by Spock +* Bootstrap Weld SE container with + * Disabled discovery + * Disabled concurrent deployment +* Inject into all `@Shared` fields of the specification that are annotated with `@Inject` +* Inject into all non-`@Shared` fields of the specification that are annotated with `@Inject` +* Inject into `setup`, feature, and `cleanup` method parameters of your specification + * If the parameter is no data variable + * If no other Spock extension already provided a value for it + * If the type of the parameter matches a known and resolvable bean + * By default, Weld is greedy and will try to resolve all parameters which are known as bean types in the container + * If this behaviour should be different, refer to [additional configuration section](#explicit-parameter-injection) +* Shut down the container after iteration is done + +Here is a simple example using the default plus one additional annotation (`@AddPackages`). + +_**Example:**_ +```groovy +@EnableAutoWeld +@AddPackages(Engine) // turn all legitimate classes inside Engine's package into CDI beans +class BasicAutomagicTest extends Specification { + @Inject + private V8 v8Engine + + @Inject + private V6 v6Engine + + def test() { + expect: + v8Engine != null + v6Engine != null + } +} +``` + +The default behaviour is powerful enough to handle basic cases where you simply want to inject a bean and make +assertions on it. However, it will not be enough if you want to, say, test your CDI extensions, enable custom +interceptors or make sure certain scopes are active. Or if you want to inject interfaces instead of implementations +of beans. For those cases, and many others, there are special annotations you can use - we will go over them, +one at a time. At the end there is an example showing several of them. + +### `@ActivateScopes` + +Normally, only `@ApplicationScoped` and `@Dependent` beans work without any additional settings. +`@ActivateScopes` annotation allows you to list scopes which are to be activated for the lifetime +of the Weld container which is depending on the `scope` setting you use. + +### `@AddBeanClasses` + +Using this annotation you can specify a list of classes which will be registered as beans with Weld container. +Note that standard rules for beans apply (proxiability for instance). + +This can be handy if you wish to operate with interfaces rather than implementation classes as the class scanning +performed by the extension cannot know for sure which class is the implementation of given interface. + +### `@AddEnabledDecorators` + +Adds the decorator class into deployment and enables it. + +### `@AddEnabledInterceptors` + +Adds the interceptor class into deployment and enables it. + +### `@AddExtensions` + +Registers one or more extensions within the Weld container. +This is the programmatic replacement for placing the extension in `META-INF`. + +### `@AddPackages` + +Adds all bean classes from listed packages to the Weld container. +Packages are selected by providing any bean class in the package. +You can also specify if this should be done recursively using the `recursive` parameter. + +### `@EnableAlternativeStereotypes` + +Enables given alternative stereotypes. + +### `@EnableAlternatives` + +Selects given alternatives for the test bean archive. + +### `@ExcludeBean` + +Excludes a bean, or multiple beans, that include a bean defining annotation (e.g. scope) from automatic discovery. +This can be helpful to allow replacing a bean class with a different implementation, typically a mock or stub. + +The type of bean to exclude is implied by the annotated field's type or annotated method's return type. +If the type is a base class or interface all beans extending / implementing that type will be excluded. + +NOTE: This annotation will only exclude beans defined by class annotations. +It will not exclude beans of the implied type that are defined by `@Produces` producer methods / fields or synthetic +beans. Also, current the implementation excludes beans based on type, disregarding any qualifiers that are specified. + +_**Example:**_ +```groovy +@EnableWeld(automagic = true) +class TestSomeFoo extends Specification { + // SomeFoo depends upon application scoped bean Foo + @Inject + SomeFoo someFoo + + @Produces + // Excludes beans with type Foo from automatic discovery + @ExcludeBean + // mockFoo is now produced in place of original Foo impl + Foo mockFoo = Stub() + + def test(Foo myFoo) { + expect: + myFoo?.bar == 'mock-foo' + } +} +``` + +### `@ExcludeBeanClasses` + +Excludes a set of classes with bean defining annotations (e.g. scopes) from automatic discovery. +This can be helpful to allow replacing bean classes with a different implementation, typically a mock or stub. + +This annotation works as an inverse of [`@AddBeanClasses`](#addbeanclasses) hence usually requires actual bean +implementation classes as parameters. + +NOTE: This annotation will only exclude beans defined by class annotations. +It will not exclude beans of the specified type that are defined by `Produces` producer methods / fields or +synthetic beans. + +## Additional Configuration + +This section describes any additional configuration options this extension offers. + +### Explicit Parameter Injection + +As mentioned above, Weld is greedy when it comes to parameter injection. +It will claim the ability to resolve any parameter which is known as a bean type inside the running CDI container, +if it is not a data variable and not already provided by another Spock extension when this one does its work. +This is mainly for usability, as it would be annoying to constantly type additional annotations to mark +which parameter should be injected and which should be left alone. + +However, we are aware that this might cause trouble if more extensions are competing for parameter resolution. +In such case, you can turn on explicit parameter resolution and Weld will only resolve parameters +which have at least one `@Qualifier` annotation on them. + +The explicit parameter injection can be enabled using the `explicitParamInjection` property in the Spock configuration +file or using the same named property of the `@EnableWeld` annotation. + +_**Example:**_ +```groovy +// all methods will now require explicit parameters +@EnableWeld(explicitParamInjection = true) +class ExplicitParamInjectionTest extends Specification { + def 'params should not be resolved by Weld'(Foo foo) { + // Weld will not attempt to resolve Foo, + // hence this test will fail unless there is another extension resolving it + } + + def 'params should be resolved by Weld'(@Default Foo foo, @MyQualifier Bar bar) { + // Weld will resolve both of the parameters + } +} +``` + +If you want to inject a bean where you would normally not use any qualifier, +you can do that using `@Default` qualifier (as shown in the example above). +This is in accordance with the CDI specification, feel free to +[read more about it](https://jakarta.ee/specifications/cdi/3.0/jakarta-cdi-spec-3.0.html#builtin_qualifiers). + +#### Flat Deployment + +Unlike [Arquillian Weld embedded container](https://github.com/arquillian/arquillian-container-weld), +weld-spock has bean archive isolation enabled by default. This behaviour can be changed by setting the system property +`org.jboss.weld.se.archive.isolation` to `false` or through the `Weld.property()` method using the same property. +If set to `false`, Weld will use a _"flat"_ deployment structure - all bean classes share the same bean archive +and all `beans.xml` descriptors are automatically merged into one. Thus, alternatives, interceptors, +and decorators selected / enabled for a bean archive will be enabled for the whole application. + +Note that this configuration only makes a difference if you run with *enabled discovery*; +it won't affect your deployment if you use the synthetic bean archive. + +### IllegalStateException in Assertion Failure Rendering + +Spock has a very handy rendering capability for failed assertions called power assertions. +This rendering shows a textual representation of all sub expressions of an assertion, +most often this is a simple `toString()` result. + +These power assertion renderings in Spock happen only when necessary, that is when the output is to be displayed. +If some of the sub expressions are CDI proxies, this can become problematic, as the Weld container is long shut down +already at the time the `toString()` method is called. This usually manifests with some of the sub expressions being +rendered like `Something$Proxy$_$$_WeldClientProxy@4303056f (renderer threw IllegalStateException)`. + +_**Example:**_ +``` +Condition not satisfied: + +first.id != second.id +| | | | | +| | | | 1239bf1f-448c-4476-9202-f98431027196 +| | | org.jboss.weld.spock.bean.AddBeanTest$IdSupplier$Proxy$_$$_WeldClientProxy@7ddfaeca (renderer threw IllegalStateException) +| | false +| 1239bf1f-448c-4476-9202-f98431027196 +org.jboss.weld.spock.bean.AddBeanTest$IdSupplier$Proxy$_$$_WeldClientProxy@7ddfaeca (renderer threw IllegalStateException) +``` + +This project contains another Spock extension that automatically triggers these renderings while the Weld container +is still running, as the result is cached by Spock. So with extension doing its work properly, the same example as +above renders like: + +_**Example:**_ +``` +Condition not satisfied: + +first.id != second.id +| | | | | +| | | | e6b47bae-a5d9-48c6-9d8e-bdffe4a00779 +| | | org.jboss.weld.spock.bean.AddBeanTest$IdSupplier@7853386b +| | false +| e6b47bae-a5d9-48c6-9d8e-bdffe4a00779 +org.jboss.weld.spock.bean.AddBeanTest$IdSupplier@7853386b +``` + +If you still see such an `IllegalStateException` in a renderer, the extension is missing some case, +so please report it as issue, optimally with a reproducer. diff --git a/spock/pom.xml b/spock/pom.xml new file mode 100644 index 00000000..c9ed1c7a --- /dev/null +++ b/spock/pom.xml @@ -0,0 +1,86 @@ + + + 4.0.0 + + + org.jboss.weld + weld-junit-parent + 4.0.0-SNAPSHOT + + + weld-spock + + + ${project.basedir}/spotbugs-exclude.xml + + + + + + org.jboss.weld.se + weld-se-core + + + + org.jboss.weld + weld-junit-common + + + + + org.spockframework + spock-core + provided + + + + + org.apache.logging.log4j + log4j-core + + + + org.junit.platform + junit-platform-testkit + + + + org.codehaus.groovy + groovy + test + + + + jakarta.ejb + jakarta.ejb-api + + + + jakarta.persistence + jakarta.persistence-api + test + + + + org.jboss.weld.module + weld-ejb + + + + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + package + + + + + diff --git a/spock/spotbugs-exclude.xml b/spock/spotbugs-exclude.xml new file mode 100644 index 00000000..0d402857 --- /dev/null +++ b/spock/spotbugs-exclude.xml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/spock/src/main/java/org/jboss/weld/spock/DisableWeld.java b/spock/src/main/java/org/jboss/weld/spock/DisableWeld.java new file mode 100644 index 00000000..a2340948 --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/DisableWeld.java @@ -0,0 +1,53 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import spock.lang.Shared; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * An annotation with which Weld can be disabled on specification or feature level if it was + * enabled globally or on specification level. + * + *

If Weld is enabled for a specification globally or by annotation with specification scope, + * and disabled for a feature, there will still be the specification scoped Weld running during the + * test and {@link Shared @Shared} fields injected from that instance, but the non-{@code @Shared} + * fields, and parameters of {@code setup}, feature, and {@code cleanup} methods will not be injected. + * + *

On any class that is not a specification and on any method that is not a feature, this annotation + * is simply ignored and has no effect. + * + *

If this annotation is applied on the same element as {@link EnableWeld @EnableWeld}, an exception + * is thrown as it is unclear which should have precedence. + * + * @author Björn Kautler + * @see EnableWeld + * @see org.jboss.weld.spock.impl.EnableWeldExtension + */ +@Retention(RUNTIME) +@Target({ TYPE, METHOD }) +@Documented +public @interface DisableWeld { +} diff --git a/spock/src/main/java/org/jboss/weld/spock/EnableWeld.java b/spock/src/main/java/org/jboss/weld/spock/EnableWeld.java new file mode 100644 index 00000000..66ca470c --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/EnableWeld.java @@ -0,0 +1,140 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import org.jboss.weld.spock.impl.EnableWeldExtension; +import spock.lang.Shared; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static org.jboss.weld.spock.EnableWeld.Scope.ITERATION; + +/** + * An annotation with which Weld can be enabled on specification or feature level if it was + * disabled globally or on specification level. + * + *

The exact effect of this annotation depends on the further properties set on it as described + * in the documentation of the individual properties. + * + *

On any class that is not a specification and on any method that is not a feature, this annotation + * is simply ignored and has no effect. + * + *

If this annotation is applied on the same element as {@link DisableWeld @DisableWeld}, an exception + * is thrown as it is unclear which should have precedence. + * + * @author Björn Kautler + * @see DisableWeld + * @see EnableWeldExtension + * @see org.jboss.weld.spock.impl.EnableWeldManualInterceptor + * @see org.jboss.weld.spock.impl.EnableWeldAutoInterceptor + */ +@Retention(RUNTIME) +@Target({ TYPE, METHOD }) +@Documented +public @interface EnableWeld { + /** + * Whether to use the {@link org.jboss.weld.spock.impl.EnableWeldManualInterceptor} ({@code false}) with which you mostly + * manually configure Weld and have full control over which beans make it into the container, or the + * {@link org.jboss.weld.spock.impl.EnableWeldAutoInterceptor} with which most things should happen automagically + * but can be adjusted using annotations. See those classes' documentation and also {@link EnableWeldExtension} for further information. + * + * @return whether to use automagic or manual logic + */ + boolean automagic() default false; + + /** + * The scope for which the Weld container should be valid and used. See the documentation of the {@code Scope} values + * for details about the individual values. + * + * @return the scope for which the Weld container should be valid and used + */ + Scope scope() default ITERATION; + + /** + * Whether to require explicit parameter injection. By default, all method parameters that are no data variables + * and are not already set by another Spock extension are checked whether they can be resolved from the Weld container. + * If this is the case, they are automatically injected, otherwise they are ignored, to be filled by a later + * running Spock extension. Using this parameter, this automatic behavior can be disabled and instead require + * that each parameter that should be injected has a qualifier annotation, like for example {@code @Default}. + * + *

If explicit parameter injection is enabled and a parameter that is not yet injected by another Spock extension + * but has a qualifier annotation cannot be resolved using the Weld container, an exception will be thrown. + * + * @return whether to require explicit parameter injection + */ + boolean explicitParamInjection() default false; + + /** + * The scope for which the Weld container should be valid and used. + */ + enum Scope { + /** + * Before an iteration (before the {@code setup} method is called) a new Weld container will be started, + * exclusively used for this iteration and after the iteration (after the {@code cleanup} method is called) + * shut down again. + * + *

The {@link Shared @Shared} fields will be injected, but only at the time the iteration starts running. + * If you have multiple such Weld instances in one specification and use the parallel execution feature of Spock, + * those Weld containers might overwrite each other's values, so be careful what you configure to not get unexpected results. + * + *

The non-{@code @Shared} fields will also be injected, as well as method parameters of {@code setup}, + * feature, and {@code cleanup} methods. + * + *

{@code setupSpec} and {@code cleanupSpec} method parameters will not be injected as at the time those + * methods are executed, the Weld container is either not yet running or already shut down. + */ + ITERATION, + + /** + * Before a feature (before the {@code setup} method of the first iteration is called) a new Weld container will be started, + * exclusively used for all iterations of this feature and after the feature (after the {@code cleanup} method of + * the last iteration is called) shut down again. + * + *

The {@link Shared @Shared} fields will be injected, but only at the time the first iteration starts running. + * If you have multiple such Weld instances in one specification and use the parallel execution feature of Spock, + * those Weld containers might overwrite each other's values, so be careful what you configure to not get unexpected results. + * + *

The non-{@code @Shared} fields will also be injected, as well as method parameters of {@code setup}, + * feature, and {@code cleanup} methods. + * + *

{@code setupSpec} and {@code cleanupSpec} method parameters will not be injected as at the time those + * methods are executed, the Weld container is either not yet running or already shut down. + */ + FEATURE, + + /** + * Before a specification (before the {@code setupSpec} method is called) a new Weld container will be started, + * exclusively used for all iterations of all features of this specification and after the specification + * (after the {@code cleanupSpec} method is called) shut down again. + * + *

The {@link Shared @Shared} fields will be injected once after the container was booted successfully. + * + *

The non-{@code @Shared} fields will also be injected, as well as method parameters of feature, + * and all fixture methods. + * + *

This scope can only be selected on a specification or in the Spock configuration file. If it is used + * for a feature annotation, an exception will be thrown. + */ + SPECIFICATION + } +} diff --git a/spock/src/main/java/org/jboss/weld/spock/WeldConfiguration.java b/spock/src/main/java/org/jboss/weld/spock/WeldConfiguration.java new file mode 100644 index 00000000..11313a19 --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/WeldConfiguration.java @@ -0,0 +1,50 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock; + +import org.jboss.weld.spock.EnableWeld.Scope; +import org.jboss.weld.spock.impl.EnableWeldExtension; +import spock.config.ConfigurationObject; + +import static org.jboss.weld.spock.EnableWeld.Scope.ITERATION; + +/** + * Configuration settings for the weld-spock extensions. + * + *

Example: + *

{@code
+ * import static org.jboss.weld.spock.EnableWeld.Scope.SPECIFICATION
+ *
+ * 'org.jboss.weld' {
+ *   enabled true // default false
+ *   automagic true // default false
+ *   scope SPECIFICATION // default ITERATION
+ *   explicitParamInjection true // default false
+ * }
+ * }
+ * + * @author Björn Kautler + * @see EnableWeldExtension + */ +@ConfigurationObject("org.jboss.weld") +public class WeldConfiguration { + public boolean enabled = false; + public boolean automagic = false; + public Scope scope = ITERATION; + public boolean explicitParamInjection = false; +} diff --git a/spock/src/main/java/org/jboss/weld/spock/WeldInitiator.java b/spock/src/main/java/org/jboss/weld/spock/WeldInitiator.java new file mode 100644 index 00000000..afbf4cfe --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/WeldInitiator.java @@ -0,0 +1,203 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock; + +import java.lang.annotation.Annotation; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; + +import jakarta.enterprise.inject.spi.Bean; +import jakarta.enterprise.inject.spi.Extension; +import jakarta.enterprise.inject.spi.InjectionPoint; +import org.jboss.weld.environment.se.Weld; +import org.jboss.weld.environment.se.WeldContainer; +import org.jboss.weld.junit.AbstractWeldInitiator; + +/** + * Weld initiator - can be used to customize the Weld SE container started by + * {@link org.jboss.weld.spock.impl.EnableWeldInterceptor}. + * + *

Example: + *

+ * @EnableWeld
+ * public class SimpleTest extends Specification {
+ *     @WeldSetup
+ *     def weld = WeldInitiator.of(Foo)
+ *
+ *     def 'test foo'() {
+ *         expect:
+ *             // Weld container is started automatically
+ *             // WeldInitiator can be used to perform programmatic lookup of beans
+ *             weld.select(Foo).get().baz == 'baz'
+ *     }
+ * }
+ * 
+ * + * @author Björn Kautler + */ +public class WeldInitiator extends AbstractWeldInitiator { + /** + * The container is configured with the result of {@link #createWeld()} method and the given bean classes are added. If any + * of added classes is an extension, it is automatically recognized and enabled. + * + * @param beanClasses + * @return a new WeldInitiator instance + * @see Weld#beanClasses(Class...) + */ + public static WeldInitiator of(Class... beanClasses) { + return from(beanClasses).build(); + } + + /** + * The container is configured through a provided {@link Weld} instance. + * + * @param weld + * @return a new WeldInitiator instance + */ + public static WeldInitiator of(Weld weld) { + return from(weld).build(); + } + + /** + * The container is configured with the result of {@link #createWeld()} method and all the classes from the test class + * package are added. + * + * @return a new WeldInitiator instance + */ + public static WeldInitiator ofTestPackage() { + return fromTestPackage().build(); + } + + /** + * The container is instructed to do automatic bean discovery, the resulting bean archive is NOT synthetic. Note that this + * requires beans.xml to be present. It is equals to {@code WeldInitiator.of(new Weld())} invocation. + * + * @return a new WeldInitiator instance + */ + public static WeldInitiator performDefaultDiscovery() { + return of(new Weld()); + } + + /** + * Create a builder instance. + * + * @param beanClasses + * @return a builder instance + * @see #of(Class...) + */ + @SuppressWarnings("unchecked") + public static Builder from(Class... beanClasses) { + Weld weld = createWeld(); + for (Class clazz : beanClasses) { + if (Extension.class.isAssignableFrom(clazz)) { + weld.addExtensions((Class) clazz); + } else { + weld.addBeanClass(clazz); + } + } + return from(weld); + } + + /** + * Create a builder instance. + * + * @param weld + * @return a builder instance + * @see #of(Weld) + */ + public static Builder from(Weld weld) { + return new Builder(weld); + } + + /** + * Create a builder instance. + * + * @return a builder instance + * @see #ofTestPackage() + */ + public static Builder fromTestPackage() { + return new Builder(null); + } + + /** + * The returned {@link Weld} instance has: + *
    + *
  • automatic discovery disabled
  • + *
  • concurrent deployment disabled
  • + *
+ * + * @return a new {@link Weld} instance suitable for testing + * @see AbstractWeldInitiator#createWeld() + */ + public static Weld createWeld() { + return AbstractWeldInitiator.createWeld(); + } + + /** + * This builder can be used to customize the final {@link WeldInitiator} instance, e.g. to activate a context for a given + * normal scope. + */ + public static final class Builder extends AbstractBuilder { + + private Builder(Weld weld) { + super(weld); + } + + @Override + protected Builder self() { + return this; + } + + @Override + protected WeldInitiator build(Weld weld, List instancesToInject, Set> scopesToActivate, Set> beans) { + return new WeldInitiator(weld, instancesToInject, scopesToActivate, beans, resources, getEjbFactory(), getPersistenceUnitFactory(), getPersistenceContextFactory()); + } + } + + private WeldInitiator(Weld weld, List instancesToInject, Set> scopesToActivate, Set> beans, + Map resources, Function ejbFactory, Function persistenceUnitFactory, + Function persistenceContextFactory) { + super(weld, instancesToInject, scopesToActivate, beans, resources, ejbFactory, persistenceUnitFactory, persistenceContextFactory); + } + + public void addObjectToInjectInto(Object instanceToInjectInto) { + instancesToInject.add(createToInject(instanceToInjectInto)); + } + + public void addObjectsToInjectInto(Set instancesToInjectInto) { + for (Object o : instancesToInjectInto) { + addObjectToInjectInto(o); + } + } + + public WeldContainer initWeld(Object testInstance) { + Weld weld = WeldInitiator.this.weld; + if (weld == null) { + // null in case of fromTestPackage() was used + weld = createWeld().addPackage(false, testInstance.getClass()); + } + + return initWeldContainer(weld); + } + + public void shutdownWeld() { + super.shutdownWeldContainer(); + } +} diff --git a/spock/src/main/java/org/jboss/weld/spock/WeldSetup.java b/spock/src/main/java/org/jboss/weld/spock/WeldSetup.java new file mode 100644 index 00000000..3420fcf0 --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/WeldSetup.java @@ -0,0 +1,35 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * An annotation used to denote a field holding a {@link WeldInitiator}. This is then picked up by + * {@link org.jboss.weld.spock.impl.EnableWeldManualInterceptor} and used for configuration. + * + * @author Björn Kautler + */ +@Retention(RUNTIME) +@Target(FIELD) +public @interface WeldSetup { +} diff --git a/spock/src/main/java/org/jboss/weld/spock/WeldSpockEnricher.java b/spock/src/main/java/org/jboss/weld/spock/WeldSpockEnricher.java new file mode 100644 index 00000000..1248a031 --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/WeldSpockEnricher.java @@ -0,0 +1,46 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock; + +import org.jboss.weld.environment.se.Weld; +import spock.lang.Specification; + +/** + * If no {@link WeldInitiator} field annotated with {@link WeldSetup} is present on a test class, or if the automagic mode is used, + * all service providers of this interface are used to enrich the default test environment. The initial {@link Weld} instance is + * created using {@link WeldInitiator#createWeld()}. + * + *

A system property with key equal to FQCN of a customizer class may be used to disable an enricher completely. E.g. for a class + * {@code org.weld.FooEnricher} use {@code -Dorg.weld.FooEnricher=false} to disable the enricher. + * + * @author Björn Kautler + */ +public interface WeldSpockEnricher { + /** + * Enrich the default test environment. + * + *

{@link Weld#initialize()} and {@link WeldInitiator.Builder#build()} methods must never be invoked in an enricher! + * + * @param testInstance the test instance for which the enricher is called; this is {@code null} + * if the enricher is called from a {@code SPECIFICATION} scoped interceptor of from a + * {@code FEATURE} scoped interceptor of a data-driven feature + * @param weld the weld instance to be customized + * @param weldInitiatorBuilder the weld initiator builder to be customized + */ + void enrich(Specification testInstance, Weld weld, WeldInitiator.Builder weldInitiatorBuilder); +} diff --git a/spock/src/main/java/org/jboss/weld/spock/auto/ActivateScopes.java b/spock/src/main/java/org/jboss/weld/spock/auto/ActivateScopes.java new file mode 100644 index 00000000..63630021 --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/auto/ActivateScopes.java @@ -0,0 +1,52 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Inherited; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Activates the listed scopes for the duration of the test. + * + * @author Björn Kautler + */ +@Retention(RUNTIME) +@Target(TYPE) +@Inherited +@Repeatable(ActivateScopes.All.class) +public @interface ActivateScopes { + Class[] value(); + + /** + * Container annotation for repeatable {@link ActivateScopes}. + * + * @author Björn Kautler + */ + @Retention(RUNTIME) + @Target(TYPE) + @Inherited + @interface All { + ActivateScopes[] value(); + } +} diff --git a/spock/src/main/java/org/jboss/weld/spock/auto/AddBeanClasses.java b/spock/src/main/java/org/jboss/weld/spock/auto/AddBeanClasses.java new file mode 100644 index 00000000..98f7c081 --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/auto/AddBeanClasses.java @@ -0,0 +1,51 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto; + +import java.lang.annotation.Inherited; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Adds the listed classes as beans to the deployed testing container. + * + * @author Björn Kautler + */ +@Retention(RUNTIME) +@Target(TYPE) +@Inherited +@Repeatable(AddBeanClasses.All.class) +public @interface AddBeanClasses { + Class[] value(); + + /** + * Container annotation for repeatable {@link AddBeanClasses}. + * + * @author Björn Kautler + */ + @Retention(RUNTIME) + @Target(TYPE) + @Inherited + @interface All { + AddBeanClasses[] value(); + } +} diff --git a/spock/src/main/java/org/jboss/weld/spock/auto/AddEnabledDecorators.java b/spock/src/main/java/org/jboss/weld/spock/auto/AddEnabledDecorators.java new file mode 100644 index 00000000..939d5615 --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/auto/AddEnabledDecorators.java @@ -0,0 +1,51 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto; + +import java.lang.annotation.Inherited; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Adds, and enables, the listed classes as CDI decorators to the deployed testing container. + * + * @author Björn Kautler + */ +@Retention(RUNTIME) +@Target(TYPE) +@Inherited +@Repeatable(AddEnabledDecorators.All.class) +public @interface AddEnabledDecorators { + Class[] value(); + + /** + * Container annotation for repeatable {@link AddEnabledDecorators}. + * + * @author Björn Kautler + */ + @Retention(RUNTIME) + @Target(TYPE) + @Inherited + @interface All { + AddEnabledDecorators[] value(); + } +} diff --git a/spock/src/main/java/org/jboss/weld/spock/auto/AddEnabledInterceptors.java b/spock/src/main/java/org/jboss/weld/spock/auto/AddEnabledInterceptors.java new file mode 100644 index 00000000..32b1ab7c --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/auto/AddEnabledInterceptors.java @@ -0,0 +1,51 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto; + +import java.lang.annotation.Inherited; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Adds, and enables, the listed classes as CDI interceptors to the deployed testing container. + * + * @author Björn Kautler + */ +@Retention(RUNTIME) +@Target(TYPE) +@Inherited +@Repeatable(AddEnabledInterceptors.All.class) +public @interface AddEnabledInterceptors { + Class[] value(); + + /** + * Container annotation for repeatable {@link AddEnabledInterceptors}. + * + * @author Björn Kautler + */ + @Retention(RUNTIME) + @Target(TYPE) + @Inherited + @interface All { + AddEnabledInterceptors[] value(); + } +} diff --git a/spock/src/main/java/org/jboss/weld/spock/auto/AddExtensions.java b/spock/src/main/java/org/jboss/weld/spock/auto/AddExtensions.java new file mode 100644 index 00000000..c4d9afef --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/auto/AddExtensions.java @@ -0,0 +1,53 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto; + +import java.lang.annotation.Inherited; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.enterprise.inject.spi.Extension; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Adds the listed classes as portable CDI extensions to the deployed testing container. + * + * @author Björn Kautler + */ +@Retention(RUNTIME) +@Target(TYPE) +@Inherited +@Repeatable(AddExtensions.All.class) +public @interface AddExtensions { + Class[] value(); + + /** + * Container annotation for repeatable {@link AddExtensions}. + * + * @author Björn Kautler + */ + @Retention(RUNTIME) + @Target(TYPE) + @Inherited + @interface All { + AddExtensions[] value(); + } +} diff --git a/spock/src/main/java/org/jboss/weld/spock/auto/AddPackages.java b/spock/src/main/java/org/jboss/weld/spock/auto/AddPackages.java new file mode 100644 index 00000000..f50c7f9c --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/auto/AddPackages.java @@ -0,0 +1,55 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto; + +import java.lang.annotation.Inherited; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Adds all bean classes from the listed packages to the deployed testing container. + * + *

Packages are selected by providing any bean class in the package. + * + * @author Björn Kautler + */ +@Retention(RUNTIME) +@Target(TYPE) +@Inherited +@Repeatable(AddPackages.All.class) +public @interface AddPackages { + Class[] value(); + + boolean recursively() default true; + + /** + * Container annotation for repeatable {@link AddPackages}. + * + * @author Björn Kautler + */ + @Retention(RUNTIME) + @Target(TYPE) + @Inherited + @interface All { + AddPackages[] value(); + } +} diff --git a/spock/src/main/java/org/jboss/weld/spock/auto/EnableAlternativeStereotypes.java b/spock/src/main/java/org/jboss/weld/spock/auto/EnableAlternativeStereotypes.java new file mode 100644 index 00000000..9b9f0192 --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/auto/EnableAlternativeStereotypes.java @@ -0,0 +1,52 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Inherited; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Adds the listed annotations as alternative stereotypes to the deployed container. + * + * @author Björn Kautler + */ +@Retention(RUNTIME) +@Target(TYPE) +@Inherited +@Repeatable(EnableAlternativeStereotypes.All.class) +public @interface EnableAlternativeStereotypes { + Class[] value(); + + /** + * Container annotation for repeatable {@link EnableAlternativeStereotypes}. + * + * @author Björn Kautler + */ + @Retention(RUNTIME) + @Target(TYPE) + @Inherited + @interface All { + EnableAlternativeStereotypes[] value(); + } +} diff --git a/spock/src/main/java/org/jboss/weld/spock/auto/EnableAlternatives.java b/spock/src/main/java/org/jboss/weld/spock/auto/EnableAlternatives.java new file mode 100644 index 00000000..cefdab4b --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/auto/EnableAlternatives.java @@ -0,0 +1,51 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto; + +import java.lang.annotation.Inherited; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Enables the listed classes as bean class alternatives in the deployed testing container. + * + * @author Björn Kautler + */ +@Retention(RUNTIME) +@Target(TYPE) +@Inherited +@Repeatable(EnableAlternatives.All.class) +public @interface EnableAlternatives { + Class[] value(); + + /** + * Container annotation for repeatable {@link EnableAlternatives}. + * + * @author Björn Kautler + */ + @Retention(RUNTIME) + @Target(TYPE) + @Inherited + @interface All { + EnableAlternatives[] value(); + } +} diff --git a/spock/src/main/java/org/jboss/weld/spock/auto/ExcludeBean.java b/spock/src/main/java/org/jboss/weld/spock/auto/ExcludeBean.java new file mode 100644 index 00000000..a85709ec --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/auto/ExcludeBean.java @@ -0,0 +1,67 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto; + +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.enterprise.inject.Produces; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * {@code @ExcludeBean} excludes a bean, or multiple beans, that include a bean defining annotation + * (e.g. scope) from automatic discovery. This can be helpful to allow replacing a bean class with a different + * implementation, typically a mock or stub. + * + *

The type of bean to exclude is implied by the annotated fields' type or annotated methods' return type. If the type + * is a base class or interface all beans extending / implementing that type will be excluded. + * + *

NOTE: This annotation will only exclude beans defined by class annotations. It will not exclude beans of the + * implied type that are defined by {@link Produces} producer methods / fields or synthetic + * beans. Also, current implementation excludes beans based on type, disregarding any qualifiers that are specified. + * + *

Example: + *

+ * @EnableWeld(automagic = true)
+ * class TestSomeFoo extends Specification {
+ *   @Inject
+ *   SomeFoo someFoo        // SomeFoo depends upon application scoped bean Foo
+ *
+ *   @Produces
+ *   @ExcludeBean           // Excludes beans with type Foo from automatic discovery
+ *   Foo mockFoo = Mock()   // mockFoo is now produced in place of original Foo impl
+ *
+ *   def test(Foo myFoo) {
+ *     expect:
+ *       myFoo?.bar == 'mock-foo'
+ *   }
+ * }
+ * 
+ * + * @author Björn Kautler + * @see ExcludeBeanClasses + */ +@Retention(RUNTIME) +@Target({ FIELD, METHOD }) +@Inherited +public @interface ExcludeBean { +} diff --git a/spock/src/main/java/org/jboss/weld/spock/auto/ExcludeBeanClasses.java b/spock/src/main/java/org/jboss/weld/spock/auto/ExcludeBeanClasses.java new file mode 100644 index 00000000..f7b2072a --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/auto/ExcludeBeanClasses.java @@ -0,0 +1,81 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto; + +import java.lang.annotation.Inherited; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.enterprise.inject.Produces; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * {@code @ExcludeBeanClasses} excludes a set of classes with bean defining annotations (e.g. scopes) from automatic + * discovery. This can be helpful to allow replacing bean classes with a different implementation, typically a mock + * or stub. + * + *

This annotation works as an inverse of {@link AddBeanClasses} hence usually requires actual bean implementation + * classes as parameters. + * + *

NOTE: This annotation will only exclude beans defined by class annotations. It will not exclude beans of the + * specified type that are defined by {@link Produces} producer methods / fields or synthetic beans. + * + *

Example: + *

+ * @EnableWeld(automagic = true)
+ * @ExcludeBeanClasses(Foo)   // Excludes Foo bean class from automatic discovery
+ * class TestSomeFoo extends Specification {
+ *   @Inject
+ *   SomeFoo someFoo          // SomeFoo depends upon application scoped bean Foo
+ *
+ *   @Produces
+ *   Foo mockFoo = Mock()     // mockFoo is now produced in place of original Foo impl
+ *
+ *   @Test
+ *   def test(Foo myFoo) {
+ *     expect:
+ *       myFoo?.bar == 'mock-foo'
+ *   }
+ * }
+ * 
+ * + * @author Björn Kautler + * @see ExcludeBean + */ +@Retention(RUNTIME) +@Target(TYPE) +@Inherited +@Repeatable(ExcludeBeanClasses.All.class) +public @interface ExcludeBeanClasses { + Class[] value(); + + /** + * Container annotation for repeatable {@link ExcludeBeanClasses}. + * + * @author Björn Kautler + */ + @Retention(RUNTIME) + @Target(TYPE) + @Inherited + @interface All { + ExcludeBeanClasses[] value(); + } +} diff --git a/spock/src/main/java/org/jboss/weld/spock/impl/ClassScanning.java b/spock/src/main/java/org/jboss/weld/spock/impl/ClassScanning.java new file mode 100644 index 00000000..aa0da2ef --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/impl/ClassScanning.java @@ -0,0 +1,345 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.impl; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import jakarta.decorator.Decorator; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.context.NormalScope; +import jakarta.enterprise.inject.Instance; +import jakarta.enterprise.inject.Produces; +import jakarta.enterprise.inject.Stereotype; +import jakarta.enterprise.inject.spi.Extension; +import jakarta.inject.Inject; +import jakarta.inject.Qualifier; +import jakarta.interceptor.Interceptor; +import org.jboss.weld.environment.se.Weld; +import org.jboss.weld.spock.auto.AddBeanClasses; +import org.jboss.weld.spock.auto.AddEnabledDecorators; +import org.jboss.weld.spock.auto.AddEnabledInterceptors; +import org.jboss.weld.spock.auto.AddExtensions; +import org.jboss.weld.spock.auto.AddPackages; +import org.jboss.weld.spock.auto.EnableAlternativeStereotypes; +import org.jboss.weld.spock.auto.EnableAlternatives; +import org.jboss.weld.spock.auto.ExcludeBean; +import org.jboss.weld.spock.auto.ExcludeBeanClasses; +import org.junit.platform.commons.support.AnnotationSupport; +import org.junit.platform.commons.util.CollectionUtils; +import org.junit.platform.commons.util.Preconditions; +import org.spockframework.runtime.model.FeatureMetadata; + +import static java.util.Arrays.asList; +import static java.util.Arrays.stream; +import static org.junit.platform.commons.support.AnnotationSupport.findAnnotatedFields; +import static org.junit.platform.commons.support.AnnotationSupport.findAnnotatedMethods; +import static org.junit.platform.commons.support.AnnotationSupport.isAnnotated; +import static org.junit.platform.commons.support.HierarchyTraversalMode.BOTTOM_UP; +import static org.junit.platform.commons.support.ReflectionSupport.findMethods; +import static org.spockframework.util.Identifiers.CLEANUP_METHOD; +import static org.spockframework.util.Identifiers.CLEANUP_SPEC_METHOD; +import static org.spockframework.util.Identifiers.SETUP_METHOD; +import static org.spockframework.util.Identifiers.SETUP_SPEC_METHOD; + +/** + * Provides automagic bean class discovery for a test class instance. + * + * @author Björn Kautler + */ +class ClassScanning { + static void scanForRequiredBeanClasses(Class testClass, Weld weld, boolean explicitInjection) { + List> classesToProcess = new ArrayList<>(); + classesToProcess.add(testClass); + + Set> foundClasses = new HashSet<>(); + Set excludedBeanTypes = new HashSet<>(); + Set> excludedBeanClasses = new HashSet<>(); + + while (!classesToProcess.isEmpty()) { + Class currClass = classesToProcess.remove(0); + + if (foundClasses.contains(currClass) || + excludedBeanTypes.contains(currClass) || excludedBeanClasses.contains(currClass) || + currClass.isPrimitive() || currClass.isSynthetic() || + currClass.getName().startsWith("java") || currClass.getName().startsWith("sun")) { + continue; + } + + foundClasses.add(currClass); + + findAnnotatedFields(currClass, ExcludeBean.class).stream() + .map(Field::getType) + .forEach(excludedBeanTypes::add); + + findAnnotatedMethods(currClass, ExcludeBean.class, BOTTOM_UP).stream() + .map(Method::getReturnType) + .forEach(excludedBeanTypes::add); + + findAnnotatedFields(currClass, Inject.class).stream() + .map(ClassScanning::unwrapInstanceTypeParameter) + .forEach(cls -> addClassesToProcess(classesToProcess, cls)); + + findAnnotatedMethods(currClass, Inject.class, BOTTOM_UP).stream() + .map(Method::getReturnType) + .forEach(cls -> addClassesToProcess(classesToProcess, cls)); + + findFirstAnnotatedConstructor(currClass, Inject.class) + .map(Stream::of).orElseGet(Stream::empty) + .flatMap(cons -> getExecutableParameterTypes(cons, explicitInjection).stream()) + .forEach(cls -> addClassesToProcess(classesToProcess, cls)); + + findAnnotatedDeclaredFields(currClass, Produces.class).stream() + .map(Field::getType) + .forEach(cls -> addClassesToProcess(classesToProcess, cls)); + + findAnnotatedDeclaredMethods(currClass, Produces.class).stream() + .flatMap(method -> + Stream.concat( + getExecutableParameterTypes(method, explicitInjection).stream(), + Stream.of(method.getReturnType()) + ) + ) + .forEach(cls -> addClassesToProcess(classesToProcess, cls)); + + findAnnotatedMethods(currClass, FeatureMetadata.class, BOTTOM_UP).stream() + .flatMap(method -> getExecutableParameterTypes(method, explicitInjection).stream()) + .forEach(cls -> addClassesToProcess(classesToProcess, cls)); + + findMethods(currClass, method -> SETUP_SPEC_METHOD.equals(method.getName()), BOTTOM_UP).stream() + .flatMap(method -> getExecutableParameterTypes(method, explicitInjection).stream()) + .forEach(cls -> addClassesToProcess(classesToProcess, cls)); + + findMethods(currClass, method -> SETUP_METHOD.equals(method.getName()), BOTTOM_UP).stream() + .flatMap(method -> getExecutableParameterTypes(method, explicitInjection).stream()) + .forEach(cls -> addClassesToProcess(classesToProcess, cls)); + + findMethods(currClass, method -> CLEANUP_METHOD.equals(method.getName()), BOTTOM_UP).stream() + .flatMap(method -> getExecutableParameterTypes(method, explicitInjection).stream()) + .forEach(cls -> addClassesToProcess(classesToProcess, cls)); + + findMethods(currClass, method -> CLEANUP_SPEC_METHOD.equals(method.getName()), BOTTOM_UP).stream() + .flatMap(method -> getExecutableParameterTypes(method, explicitInjection).stream()) + .forEach(cls -> addClassesToProcess(classesToProcess, cls)); + + AnnotationSupport.findRepeatableAnnotations(currClass, AddPackages.class) + .forEach(ann -> + stream(ann.value()) + .distinct() + .forEach(cls -> weld.addPackage(ann.recursively(), cls))); + + AnnotationSupport.findRepeatableAnnotations(currClass, AddBeanClasses.class).stream() + .flatMap(ann -> stream(ann.value())) + .distinct() + .forEach(it -> { + classesToProcess.add(it); + weld.addBeanClass(it); + }); + + AnnotationSupport.findRepeatableAnnotations(currClass, AddExtensions.class).stream() + .flatMap(ann -> stream(ann.value())) + .distinct() + .map(ClassScanning::createExtension) + .forEach(weld::addExtension); + + AnnotationSupport.findRepeatableAnnotations(currClass, AddEnabledInterceptors.class).stream() + .flatMap(ann -> stream(ann.value())) + .distinct() + .forEach(interceptor -> { + classesToProcess.add(interceptor); + weld.addInterceptor(interceptor); + weld.addBeanClass(interceptor); + }); + + AnnotationSupport.findRepeatableAnnotations(currClass, AddEnabledDecorators.class).stream() + .flatMap(ann -> stream(ann.value())) + .distinct() + .forEach(decorator -> { + classesToProcess.add(decorator); + weld.addDecorator(decorator); + weld.addBeanClass(decorator); + }); + + AnnotationSupport.findRepeatableAnnotations(currClass, EnableAlternatives.class).stream() + .flatMap(ann -> stream(ann.value())) + .distinct() + .forEach(weld::addAlternative); + + AnnotationSupport.findRepeatableAnnotations(currClass, EnableAlternativeStereotypes.class).stream() + .flatMap(ann -> stream(ann.value())) + .distinct() + .forEach(weld::addAlternativeStereotype); + + AnnotationSupport.findRepeatableAnnotations(currClass, ExcludeBeanClasses.class).stream() + .flatMap(ann -> stream(ann.value())) + .distinct() + .forEach(excludedBeanClasses::add); + } + + for (Class foundClass : foundClasses) { + if (hasBeanDefiningAnnotation(foundClass)) { + weld.addBeanClass(foundClass); + } + } + + weld.addExtension(new ExcludedBeansExtension(excludedBeanTypes, excludedBeanClasses)); + } + + private static void addClassesToProcess(Collection> classesToProcess, Type type) { + if (type instanceof Class) { + classesToProcess.add((Class) type); + } else if (type instanceof ParameterizedType) { + ParameterizedType ptype = (ParameterizedType) type; + + classesToProcess.add((Class) ptype.getRawType()); + + for (Type arg : ptype.getActualTypeArguments()) { + addClassesToProcess(classesToProcess, arg); + } + } + } + + private static List> getExecutableParameterTypes(Executable executable, boolean explicitInjection) { + List> types = new ArrayList<>(); + + if (explicitInjection) { + Annotation[][] paramAnns = executable.getParameterAnnotations(); + Class[] paramTypes = executable.getParameterTypes(); + for (int c = 0; c < paramTypes.length; ++c) { + if (stream(paramAnns[c]).anyMatch(ClassScanning::isBeanParameterAnnotation)) { + types.add(paramTypes[c]); + } + } + } else { + types.addAll(asList(executable.getParameterTypes())); + } + + return types; + } + + private static Extension createExtension(Class clazz) { + try { + return clazz.getDeclaredConstructor().newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static boolean isBeanParameterAnnotation(Annotation ann) { + return isAnnotated(ann.annotationType(), Qualifier.class); + } + + private static boolean hasBeanDefiningAnnotation(Class clazz) { + return isAnnotated(clazz, NormalScope.class) || isAnnotated(clazz, Dependent.class) || + isAnnotated(clazz, Interceptor.class) || isAnnotated(clazz, Decorator.class) || + isAnnotated(clazz, Stereotype.class); + } + + private static List findAllFieldsInHierarchy(Class clazz) { + Preconditions.notNull(clazz, "Class must not be null"); + List localFields = getDeclaredFields(clazz).stream(). + filter((field) -> !field.isSynthetic()) + .collect(Collectors.toList()); + List superclassFields = getSuperclassFields(clazz).stream() + .filter((field) -> !isMethodShadowedByLocalFields(field, localFields)) + .collect(Collectors.toList()); + List methods = new ArrayList<>(); + methods.addAll(superclassFields); + methods.addAll(localFields); + + return methods; + } + + private static List getSuperclassFields(Class clazz) { + Class superclass = clazz.getSuperclass(); + return superclass != null && superclass != Object.class ? findAllFieldsInHierarchy(superclass) : Collections.emptyList(); + } + + private static List getDeclaredFields(Class clazz) { + return asList(clazz.getDeclaredFields()); + } + + private static List getDeclaredMethods(Class clazz) { + return asList(clazz.getDeclaredMethods()); + } + + private static boolean isMethodShadowedByLocalFields(Field field, List localFields) { + return localFields.stream() + .anyMatch((local) -> isFieldShadowedBy(field, local)); + } + + private static boolean isFieldShadowedBy(Field upper, Field lower) { + return upper.getType().equals(lower.getType()); + } + + private static List findAnnotatedDeclaredFields(Class clazz, Class annotationType) { + return getDeclaredFields(clazz).stream() + .filter((field) -> isAnnotated(field, annotationType)) + .collect(CollectionUtils.toUnmodifiableList()); + } + + private static List findAnnotatedDeclaredMethods(Class clazz, Class annotationType) { + return getDeclaredMethods(clazz).stream() + .filter((field) -> isAnnotated(field, annotationType)) + .collect(CollectionUtils.toUnmodifiableList()); + } + + private static List> getDeclaredConstructors(Class clazz) { + return asList(clazz.getDeclaredConstructors()); + } + + private static Optional> findFirstAnnotatedConstructor(Class clazz, Class annotationType) { + Optional> found = getDeclaredConstructors(clazz).stream() + .filter((cons) -> isAnnotated(cons, annotationType)) + .findFirst(); + + if (found.isPresent() || clazz.getSuperclass() == null) { + return found; + } + + return findFirstAnnotatedConstructor(clazz.getSuperclass(), annotationType); + } + + private static Class unwrapInstanceTypeParameter(Field field) { + Class type = field.getType(); + if (type.equals(Instance.class)) { + ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType(); + Type typeParameter = parameterizedType.getActualTypeArguments()[0]; + if (typeParameter instanceof ParameterizedType) { + type = (Class) ((ParameterizedType) typeParameter).getRawType(); + } else { + type = (Class) typeParameter; + } + } + return type; + } +} diff --git a/spock/src/main/java/org/jboss/weld/spock/impl/EagerExceptionRenderer.java b/spock/src/main/java/org/jboss/weld/spock/impl/EagerExceptionRenderer.java new file mode 100644 index 00000000..75a90def --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/impl/EagerExceptionRenderer.java @@ -0,0 +1,56 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.impl; + +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import org.spockframework.runtime.SpockAssertionError; +import org.spockframework.runtime.extension.IGlobalExtension; +import org.spockframework.runtime.model.FeatureInfo; +import org.spockframework.runtime.model.SpecInfo; + +/** + * A global Spock extension that eagerly renders exceptions, otherwise {@code toString()} might be called + * on a CDI proxy when the container is shut down already and the call cannot be done. + * + *

If in a power assertion output you see something like + * {@code Something$Proxy$_$$_WeldClientProxy@4303056f (renderer threw IllegalStateException)}, + * this extension might miss some places where to eagerly render the exception, and you should + * open an issue with a reproducer. + * + * @author Björn Kautler + */ +public class EagerExceptionRenderer implements IGlobalExtension { + @Override + public void visitSpec(SpecInfo spec) { + Stream + .concat( + StreamSupport.stream(spec.getAllFixtureMethods().spliterator(), false), + spec.getAllFeatures().stream().map(FeatureInfo::getFeatureMethod)) + .forEach(method -> + method.addInterceptor(invocation -> { + try { + invocation.proceed(); + } catch (SpockAssertionError spockAssertionError) { + spockAssertionError.toString(); + throw spockAssertionError; + } + })); + } +} diff --git a/spock/src/main/java/org/jboss/weld/spock/impl/EnableWeldAutoInterceptor.java b/spock/src/main/java/org/jboss/weld/spock/impl/EnableWeldAutoInterceptor.java new file mode 100644 index 00000000..02816f91 --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/impl/EnableWeldAutoInterceptor.java @@ -0,0 +1,129 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.impl; + +import java.util.Arrays; +import java.util.List; + +import org.jboss.weld.environment.se.Weld; +import org.jboss.weld.spock.EnableWeld; +import org.jboss.weld.spock.WeldInitiator; +import org.jboss.weld.spock.WeldSetup; +import org.jboss.weld.spock.WeldSpockEnricher; +import org.jboss.weld.spock.auto.ActivateScopes; +import org.jboss.weld.spock.auto.AddBeanClasses; +import org.jboss.weld.spock.auto.AddEnabledDecorators; +import org.jboss.weld.spock.auto.AddEnabledInterceptors; +import org.jboss.weld.spock.auto.AddExtensions; +import org.jboss.weld.spock.auto.AddPackages; +import org.jboss.weld.spock.auto.EnableAlternativeStereotypes; +import org.jboss.weld.spock.auto.EnableAlternatives; +import org.jboss.weld.spock.auto.ExcludeBean; +import org.jboss.weld.spock.auto.ExcludeBeanClasses; +import org.spockframework.runtime.InvalidSpecException; +import org.spockframework.runtime.extension.IMethodInvocation; +import org.spockframework.runtime.model.FieldInfo; +import org.spockframework.runtime.model.SpecInfo; +import spock.lang.Specification; + +import static java.lang.String.format; +import static java.util.stream.Collectors.joining; +import static java.util.stream.Collectors.toList; +import static org.jboss.weld.spock.impl.ClassScanning.scanForRequiredBeanClasses; + +/** + * An alternative to {@link EnableWeldManualInterceptor} allowing to fully leverage an annotation based configuration approach. + * When selected by {@link EnableWeld#automagic()}, this interceptor will attempt to resolve all beans used in the test class + * and automatically adds them to the Weld container while bootstrapping it. + * + *

There are quite some annotations which can be used on the test class and on any discovered bean to configure it further. + * + *

Having a {@link WeldSetup @WeldSetup} annotated field in the specification or a super specification results in an + * exception, because it would not be considered and thus is a sign that the manual interceptor should be used, or that + * the field is a left-over from switching and should be removed. + * + *

Furthermore, all discovered {@link WeldSpockEnricher}s are invoked after the annotations are processed. + * + * @author Björn Kautler + * @see ActivateScopes + * @see AddBeanClasses + * @see AddEnabledDecorators + * @see AddEnabledInterceptors + * @see AddExtensions + * @see AddPackages + * @see EnableAlternatives + * @see EnableAlternativeStereotypes + * @see ExcludeBean + * @see ExcludeBeanClasses + * @see EnableWeld + * @see WeldSpockEnricher + */ +class EnableWeldAutoInterceptor extends EnableWeldInterceptor { + private final boolean explicitParamInjection; + + public EnableWeldAutoInterceptor(List weldSpockEnrichers, boolean explicitParamInjection) { + super(weldSpockEnrichers); + this.explicitParamInjection = explicitParamInjection; + } + + @Override + protected WeldInitiator weldInit(IMethodInvocation invocation) { + Specification testInstance = (Specification) invocation.getInstance(); + + SpecInfo spec = invocation.getSpec(); + List weldSetupFields = spec + .getAllFields() + .stream() + .filter(field -> field.isAnnotationPresent(WeldSetup.class)) + .collect(toList()); + + if (weldSetupFields.size() > 0) { + throw new InvalidSpecException(weldSetupFields + .stream() + .map(f -> format("Field '%s' with type %s which is in %s", f.getName(), f.getType(), f.getParent().getDisplayName())) + .collect(joining("\n", "When using automagic mode, no @WeldSetup annotated field should be present! Fields found:\n", ""))); + } + + Weld weld = WeldInitiator.createWeld(); + WeldInitiator.Builder builder = WeldInitiator.from(weld); + + scanForRequiredBeanClasses(spec.getReflection(), weld, explicitParamInjection); + + weld.addBeanClasses(spec.getReflection()); + weld.addExtension(new TestInstanceInjectionExtension<>(testInstance)); + + spec + .getSpecsBottomToTop() + .stream() + .map(s -> s.getAnnotationsByType(ActivateScopes.class)) + .flatMap(Arrays::stream) + .map(ActivateScopes::value) + .flatMap(Arrays::stream) + .forEach(builder::activate); + + // Apply discovered enrichers + for (WeldSpockEnricher enricher : weldSpockEnrichers) { + String property = System.getProperty(enricher.getClass().getName()); + if (property == null || Boolean.parseBoolean(property)) { + enricher.enrich((testInstance == invocation.getSharedInstance()) ? null : testInstance, weld, builder); + } + } + + return builder.build(); + } +} diff --git a/spock/src/main/java/org/jboss/weld/spock/impl/EnableWeldExtension.java b/spock/src/main/java/org/jboss/weld/spock/impl/EnableWeldExtension.java new file mode 100644 index 00000000..26d8987b --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/impl/EnableWeldExtension.java @@ -0,0 +1,236 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.impl; + +import java.util.List; +import java.util.Optional; +import java.util.ServiceLoader; +import java.util.stream.Stream; + +import org.jboss.weld.spock.DisableWeld; +import org.jboss.weld.spock.EnableWeld; +import org.jboss.weld.spock.EnableWeld.Scope; +import org.jboss.weld.spock.WeldConfiguration; +import org.jboss.weld.spock.WeldSpockEnricher; +import org.jboss.weld.util.collections.ImmutableList; +import org.spockframework.runtime.InvalidSpecException; +import org.spockframework.runtime.extension.IGlobalExtension; +import org.spockframework.runtime.model.FeatureInfo; +import org.spockframework.runtime.model.MethodInfo; +import org.spockframework.runtime.model.SpecInfo; +import spock.lang.Shared; + +import static org.jboss.weld.spock.EnableWeld.Scope.FEATURE; +import static org.jboss.weld.spock.EnableWeld.Scope.ITERATION; +import static org.jboss.weld.spock.EnableWeld.Scope.SPECIFICATION; + +/** + * A global Spock extension evaluating the {@link EnableWeld @EnableWeld}, and {@link DisableWeld @DisableWeld} annotations, + * and the Spock configuration file options. + * + *

If a feature has an {@code @EnableWeld} or {@code @DisableWeld} annotation applied, this is what is effective. + * If Weld is disabled, no container will be started for the feature or the iterations and no non-{@link Shared @Shared} + * fields, or method parameters will be injected. However, if a for the specification a {@code SPECIFICATION} scoped + * Weld was booted due to annotation or configuration file options, this container will have injected instances into + * the {@code @Shared} fields already. + * + *

If a feature has neither of the two annotations applied, the configuration of the specification is inherited. + * + *

If a specification has an {@code @EnableWeld} or {@code @DisableWeld} annotation applied, this is effective for + * all features that do not have an own annotation. It will have the same effect as if the annotation is copied to all + * features that have none of the two annotations already, except if scope {@code SPECIFICATION} is selected, as this + * is only valid in a specification level annotation or the Spock configuration file. + * + *

If a specification has neither of the two annotations applied, the super specifications are searched in order + * and if an annotated one is found, its annotation is effective as if it were on the specification directly. + * + *

If also no super specification has any of the annotations, the settings from the Spock configuration file + * or the respective default settings are effective. + * + * @author Björn Kautler + * @see EnableWeld + * @see DisableWeld + * @see WeldConfiguration + */ +public class EnableWeldExtension implements IGlobalExtension { + private final WeldConfiguration weldConfiguration; + private volatile List weldSpockEnrichers; + + public EnableWeldExtension(WeldConfiguration weldConfiguration) { + this.weldConfiguration = weldConfiguration; + } + + @Override + public void start() { + ImmutableList.Builder enrichers = ImmutableList.builder(); + ServiceLoader.load(WeldSpockEnricher.class).forEach(enrichers::add); + weldSpockEnrichers = enrichers.build(); + } + + @Override + public void visitSpec(SpecInfo spec) { + Optional optionalAnnotatedSpec = spec + .getSpecsBottomToTop() + .stream() + .filter(specInfo -> specInfo.isAnnotationPresent(EnableWeld.class) || specInfo.isAnnotationPresent(DisableWeld.class)) + .findFirst(); + + boolean doEnableWeldForSpec; + boolean specAutomagic; + Scope specScope; + boolean specExplicitParamInjection; + if (optionalAnnotatedSpec.isPresent()) { + SpecInfo annotatedSpec = optionalAnnotatedSpec.get(); + EnableWeld enableWeld = annotatedSpec.getAnnotation(EnableWeld.class); + boolean enableWeldForSpec = enableWeld != null; + boolean disableWeldForSpec = annotatedSpec.isAnnotationPresent(DisableWeld.class); + + if (enableWeldForSpec && disableWeldForSpec) { + throw new InvalidSpecException("@EnableWeld and @DisableWeld must not be used on the same spec: " + annotatedSpec.getDisplayName()); + } + + if (enableWeldForSpec) { + doEnableWeldForSpec = true; + specAutomagic = enableWeld.automagic(); + specScope = enableWeld.scope(); + specExplicitParamInjection = enableWeld.explicitParamInjection(); + } else { + doEnableWeldForSpec = false; + specAutomagic = false; + specScope = null; + specExplicitParamInjection = false; + } + } else { + doEnableWeldForSpec = weldConfiguration.enabled; + specAutomagic = weldConfiguration.automagic; + specScope = weldConfiguration.scope == null ? ITERATION : weldConfiguration.scope; + specExplicitParamInjection = weldConfiguration.explicitParamInjection; + } + + // boot Weld around specification and inject shared fields + EnableWeldInterceptor enableWeldInterceptorForSpec; + if (doEnableWeldForSpec && (specScope == SPECIFICATION)) { + enableWeldInterceptorForSpec = specAutomagic + ? new EnableWeldAutoInterceptor(weldSpockEnrichers, specExplicitParamInjection) + : new EnableWeldManualInterceptor(weldSpockEnrichers); + spec.addInterceptor(enableWeldInterceptorForSpec); + + // inject parameters for specification fixture methods + Stream + .concat( + spec.getSetupSpecMethods().stream(), + spec.getCleanupSpecMethods().stream()) + .forEach(method -> attachParameterInjector(method, enableWeldInterceptorForSpec, specExplicitParamInjection)); + } else { + enableWeldInterceptorForSpec = null; + } + + spec + .getAllFeatures() + .forEach(feature -> visitFeature(feature, doEnableWeldForSpec, specAutomagic, specScope, + specExplicitParamInjection, enableWeldInterceptorForSpec)); + } + + private void visitFeature(FeatureInfo feature, boolean doEnableWeldForSpec, boolean specAutomagic, Scope specScope, + boolean specExplicitParamInjection, EnableWeldInterceptor enableWeldInterceptorForSpec) { + MethodInfo featureMethod = feature.getFeatureMethod(); + EnableWeld enableWeld = featureMethod.getAnnotation(EnableWeld.class); + boolean enableWeldForFeature = enableWeld != null; + boolean disableWeldForFeature = featureMethod.isAnnotationPresent(DisableWeld.class); + + if (enableWeldForFeature && disableWeldForFeature) { + throw new InvalidSpecException("@EnableWeld and @DisableWeld must not be used on the same feature: " + feature.getDisplayName()); + } + + boolean doEnableWeldForFeature; + boolean featureAutomagic; + Scope featureScope; + boolean featureExplicitParamInjection; + if (enableWeldForFeature) { + doEnableWeldForFeature = true; + featureAutomagic = enableWeld.automagic(); + featureScope = enableWeld.scope(); + if (featureScope.compareTo(FEATURE) > 0) { + throw new InvalidSpecException("@EnableWeld on feature cannot have broader scope than FEATURE on feature: " + feature.getDisplayName()); + } + featureExplicitParamInjection = enableWeld.explicitParamInjection(); + } else if (disableWeldForFeature) { + doEnableWeldForFeature = false; + featureAutomagic = false; + featureScope = null; + featureExplicitParamInjection = false; + } else { + doEnableWeldForFeature = doEnableWeldForSpec; + featureAutomagic = specAutomagic; + featureScope = specScope; + featureExplicitParamInjection = specExplicitParamInjection; + } + + if (doEnableWeldForFeature) { + EnableWeldInterceptor enableWeldInterceptorForFeature; + + // boot Weld around feature or iteration and inject shared fields + switch (featureScope) { + case SPECIFICATION: + enableWeldInterceptorForFeature = enableWeldInterceptorForSpec; + enableWeldInterceptorForFeature.handleFeature(feature); + break; + + case FEATURE: + enableWeldInterceptorForFeature = featureAutomagic + ? new EnableWeldAutoInterceptor(weldSpockEnrichers, featureExplicitParamInjection) + : new EnableWeldManualInterceptor(weldSpockEnrichers); + enableWeldInterceptorForFeature.handleFeature(feature); + feature.addInterceptor(enableWeldInterceptorForFeature); + break; + + case ITERATION: + enableWeldInterceptorForFeature = featureAutomagic + ? new EnableWeldAutoInterceptor(weldSpockEnrichers, featureExplicitParamInjection) + : new EnableWeldManualInterceptor(weldSpockEnrichers); + enableWeldInterceptorForFeature.handleFeature(feature); + feature.addIterationInterceptor(enableWeldInterceptorForFeature); + break; + + default: + throw new AssertionError(); + } + + // inject non-shared fields + feature.addIterationInterceptor(enableWeldInterceptorForFeature.getTestInstanceInjector()); + + // inject parameters for iteration methods + Stream.Builder streamBuilder = Stream.builder(); + feature.getSpec().getSetupMethods().forEach(streamBuilder); + streamBuilder.add(featureMethod); + feature.getSpec().getCleanupMethods().forEach(streamBuilder); + streamBuilder + .build() + .forEach(method -> attachParameterInjector(method, enableWeldInterceptorForFeature, featureExplicitParamInjection)); + } + } + + private void attachParameterInjector(MethodInfo method, EnableWeldInterceptor enableWeldInterceptor, boolean explicitParamInjection) { + int amountOfParameters = method.getReflection().getParameters().length; + int amountOfDataVariables = method.getFeature() == null ? 0 : method.getFeature().getDataVariables().size(); + // only attach if there could be injectable arguments + if (amountOfParameters > amountOfDataVariables) { + method.addInterceptor(enableWeldInterceptor.getParameterInjector(explicitParamInjection)); + } + } +} diff --git a/spock/src/main/java/org/jboss/weld/spock/impl/EnableWeldInterceptor.java b/spock/src/main/java/org/jboss/weld/spock/impl/EnableWeldInterceptor.java new file mode 100644 index 00000000..3b343bda --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/impl/EnableWeldInterceptor.java @@ -0,0 +1,162 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.impl; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Parameter; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + +import jakarta.enterprise.inject.spi.BeanManager; +import org.jboss.weld.inject.WeldInstance; +import org.jboss.weld.spock.WeldInitiator; +import org.jboss.weld.spock.WeldSpockEnricher; +import org.spockframework.runtime.extension.IMethodInterceptor; +import org.spockframework.runtime.extension.IMethodInvocation; +import org.spockframework.runtime.model.FeatureInfo; + +import static java.util.Collections.singleton; +import static java.util.Collections.synchronizedMap; +import static java.util.stream.Collectors.toList; +import static org.spockframework.runtime.model.MethodInfo.MISSING_ARGUMENT; + +/** + * A Spock interceptor, that serves as base for the manual and automatic interceptors and has the common logic. + * It first calls the custom logic of the subclass, then adds the shared instance as injection target, initializes + * the Weld container and after invocation proceeded, shuts down the container. It also provides methods to get a + * test instance injector and a parameter injector as these need to be attached to varying extension points, + * depending on the annotation configuration. + * + * @author Björn Kautler + */ +abstract class EnableWeldInterceptor implements IMethodInterceptor { + protected final List weldSpockEnrichers; + private final Map weldInitiators = synchronizedMap(new WeakHashMap<>()); + private final List handledFeatures = new CopyOnWriteArrayList<>(); + + public EnableWeldInterceptor(List weldSpockEnrichers) { + this.weldSpockEnrichers = weldSpockEnrichers; + } + + protected abstract WeldInitiator weldInit(IMethodInvocation invocation); + + @Override + public void intercept(IMethodInvocation invocation) throws Throwable { + WeldInitiator weldInitiator = weldInit(invocation); + weldInitiator.addObjectToInjectInto(invocation.getSharedInstance()); + weldInitiator.initWeld(invocation.getInstance()); + try { + Object id = (invocation.getIteration() == null) ? null : invocation.getInstance(); + weldInitiators.put(id, weldInitiator); + invocation.proceed(); + } finally { + weldInitiator.shutdownWeld(); + } + } + + public IMethodInterceptor getTestInstanceInjector() { + return invocation -> { + Object testInstance = invocation.getInstance(); + + WeldInitiator weldInitiator = weldInitiators.get(null); + if (weldInitiator == null) { + weldInitiator = weldInitiators.get(testInstance); + } + + try (AutoCloseable contextReleaser = weldInitiator.injectNonContextual(testInstance)) { + invocation.proceed(); + } + }; + } + + public void handleFeature(FeatureInfo feature) { + handledFeatures.add(feature); + } + + public IMethodInterceptor getParameterInjector(boolean explicitParamInjection) { + return invocation -> { + // this is necessary so that a specification scoped interceptor + // does not inject into a feature or iteration scoped fixture method call + // or that a feature scoped interceptor of a data-driven feature + // does not inject into another features' fixture method calls + if ((invocation.getFeature() != null) && !handledFeatures.contains(invocation.getFeature())) { + invocation.proceed(); + return; + } + + // only continue if there still are missing arguments + if (Arrays.stream(invocation.getArguments()) + .noneMatch(argument -> argument == MISSING_ARGUMENT)) { + invocation.proceed(); + return; + } + + Object testInstance = invocation.getInstance(); + + // get the sole weld initiator of this interceptor + // in case it is around a specification or parameterized feature + WeldInitiator weldInitiator = weldInitiators.get(null); + // or get the weld initiator for the current iteration + if (weldInitiator == null) { + weldInitiator = weldInitiators.get(testInstance); + } + // the fixture method interceptors for all features are triggered for each iteration + // so if there are multiple features not all have a matching initiator of course + if (weldInitiator == null) { + invocation.proceed(); + return; + } + + BeanManager beanManager = weldInitiator.getBeanManager(); + Parameter[] parameters = invocation.getMethod().getReflection().getParameters(); + Object[] arguments = invocation.getArguments(); + for (int i = 0; i < arguments.length; i++) { + Object argument = arguments[i]; + if (argument != MISSING_ARGUMENT) { + continue; + } + + Parameter parameter = parameters[i]; + List qualifiers = Arrays + .stream(parameter.getAnnotations()) + .filter(annotation -> beanManager.isQualifier(annotation.annotationType())) + .collect(toList()); + + if (explicitParamInjection) { + if (qualifiers.isEmpty()) { + continue; + } + arguments[i] = weldInitiator + .select(parameter.getType(), qualifiers.toArray(new Annotation[0])) + .get(); + } else { + WeldInstance candidates = weldInitiator + .select(parameter.getType(), qualifiers.toArray(new Annotation[0])); + if (candidates.isResolvable()) { + arguments[i] = candidates.get(); + } + } + } + + invocation.proceed(); + }; + } +} diff --git a/spock/src/main/java/org/jboss/weld/spock/impl/EnableWeldManualInterceptor.java b/spock/src/main/java/org/jboss/weld/spock/impl/EnableWeldManualInterceptor.java new file mode 100644 index 00000000..e961a39c --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/impl/EnableWeldManualInterceptor.java @@ -0,0 +1,114 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.impl; + +import java.util.List; + +import org.jboss.weld.environment.se.Weld; +import org.jboss.weld.spock.EnableWeld; +import org.jboss.weld.spock.WeldInitiator; +import org.jboss.weld.spock.WeldSetup; +import org.jboss.weld.spock.WeldSpockEnricher; +import org.spockframework.runtime.InvalidSpecException; +import org.spockframework.runtime.extension.IMethodInvocation; +import org.spockframework.runtime.model.FieldInfo; +import spock.lang.Shared; +import spock.lang.Specification; + +import static java.lang.String.format; +import static java.util.stream.Collectors.joining; +import static java.util.stream.Collectors.toList; + +/** + * A Spock interceptor that is used for manual configuration of the booted Weld container. + * + *

If the interceptor is for scope {@code SPECIFICATION}, or for a data-driven feature with scope {@code FEATURE}, + * {@link Shared @Shared} fields of the specification and its super specifications are searched for exactly one + * field that is annotated with {@link WeldSetup @WeldSetup}. + * + *

If multiple such fields are found, an exception is thrown. + * + *

If exactly one is found, and its value is not of type {@link WeldInitiator}, an exception is thrown. + * + *

Otherwise, as the type is correct, it is used as-is to initialize the Weld container. + * + *

If no field with that annotation is found, a new Weld initiator is created and the package of the test + * class is added as beans to the container. Then all discovered {@link WeldSpockEnricher}s are applied to that instance + * and the result is used to initialize the Weld container. + * + * @author Björn Kautler + * @see EnableWeld + * @see WeldSpockEnricher + */ +class EnableWeldManualInterceptor extends EnableWeldInterceptor { + public EnableWeldManualInterceptor(List weldSpockEnrichers) { + super(weldSpockEnrichers); + } + + @Override + protected WeldInitiator weldInit(IMethodInvocation invocation) { + Specification spec = (Specification) invocation.getInstance(); + boolean shared = spec == invocation.getSharedInstance(); + + List weldSetupFields = invocation + .getSpec() + .getAllFields() + .stream() + .filter(field -> (field.isShared() || field.isStatic()) == shared) + .filter(field -> field.isAnnotationPresent(WeldSetup.class)) + .collect(toList()); + + switch (weldSetupFields.size()) { + case 0: + Weld weld = WeldInitiator.createWeld(); + WeldInitiator.Builder builder = WeldInitiator.from(weld); + + weld.addPackage(false, invocation.getSpec().getReflection()); + + // Apply discovered enrichers + for (WeldSpockEnricher enricher : weldSpockEnrichers) { + String property = System.getProperty(enricher.getClass().getName()); + if (property == null || Boolean.parseBoolean(property)) { + enricher.enrich(shared ? null : spec, weld, builder); + } + } + + return builder.build(); + + case 1: + FieldInfo weldSetupField = weldSetupFields.get(0); + Object weldSetupCandidate = weldSetupField.readValue(spec); + if (!(weldSetupCandidate instanceof WeldInitiator)) { + throw new InvalidSpecException(format( + "@WeldSetup annotation should only be used on a field with a " + + "WeldInitiator value but was found on field %s with a " + + "%s value which is declared in %s", + weldSetupField.getName(), + ((weldSetupCandidate == null) ? "null" : weldSetupCandidate.getClass()), + weldSetupField.getParent().getDisplayName())); + } + return (WeldInitiator) weldSetupCandidate; + + default: + throw new InvalidSpecException(weldSetupFields + .stream() + .map(f -> format("Field '%s' with type %s which is in %s", f.getName(), f.getType(), f.getParent().getDisplayName())) + .collect(joining("\n", "Multiple @WeldSetup annotated fields found, only one is allowed! Fields found:\n", ""))); + } + } +} diff --git a/spock/src/main/java/org/jboss/weld/spock/impl/ExcludedBeansExtension.java b/spock/src/main/java/org/jboss/weld/spock/impl/ExcludedBeansExtension.java new file mode 100644 index 00000000..c304f5a4 --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/impl/ExcludedBeansExtension.java @@ -0,0 +1,58 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.impl; + +import java.lang.reflect.Type; +import java.util.Set; + +import jakarta.enterprise.context.NormalScope; +import jakarta.enterprise.event.Observes; +import jakarta.enterprise.inject.spi.Extension; +import jakarta.enterprise.inject.spi.ProcessAnnotatedType; +import jakarta.enterprise.inject.spi.WithAnnotations; +import jakarta.inject.Scope; + +/** + * Extension class that ensures selected classes are excluded as beans. + * + * @author Björn Kautler + */ +class ExcludedBeansExtension implements Extension { + private final Set excludedBeanTypes; + private final Set> excludedBeanClasses; + + ExcludedBeansExtension(Set excludedBeanTypes, Set> excludedBeanClasses) { + this.excludedBeanTypes = excludedBeanTypes; + this.excludedBeanClasses = excludedBeanClasses; + } + + void excludeBeans(@Observes @WithAnnotations({ Scope.class, NormalScope.class }) ProcessAnnotatedType pat) { + if (excludedBeanClasses.contains(pat.getAnnotatedType().getJavaClass())) { + pat.veto(); + return; + } + + Set typeClosure = pat.getAnnotatedType().getTypeClosure(); + for (Type excludedBeanType : excludedBeanTypes) { + if (typeClosure.contains(excludedBeanType)) { + pat.veto(); + return; + } + } + } +} diff --git a/spock/src/main/java/org/jboss/weld/spock/impl/TestInstanceInjectionExtension.java b/spock/src/main/java/org/jboss/weld/spock/impl/TestInstanceInjectionExtension.java new file mode 100644 index 00000000..3d4e3b3d --- /dev/null +++ b/spock/src/main/java/org/jboss/weld/spock/impl/TestInstanceInjectionExtension.java @@ -0,0 +1,76 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.impl; + +import jakarta.enterprise.context.spi.CreationalContext; +import jakarta.enterprise.event.Observes; +import jakarta.enterprise.inject.spi.Extension; +import jakarta.enterprise.inject.spi.InjectionTarget; +import jakarta.enterprise.inject.spi.ProcessAnnotatedType; +import jakarta.enterprise.inject.spi.ProcessInjectionTarget; +import jakarta.enterprise.util.AnnotationLiteral; +import jakarta.inject.Singleton; +import org.jboss.weld.injection.ForwardingInjectionTarget; + +/** + * Extension that makes a test instance appear like a regular bean even though instantiated by JUnit. + * + * @author Björn Kautler + */ +class TestInstanceInjectionExtension implements Extension { + private static final AnnotationLiteral SINGLETON_LITERAL = new AnnotationLiteral() { + }; + + private final Class testClass; + private final T testInstance; + + TestInstanceInjectionExtension(T testInstance) { + this.testClass = testInstance.getClass(); + this.testInstance = testInstance; + } + + void rewriteTestClassScope(@Observes ProcessAnnotatedType pat) { + if (pat.getAnnotatedType().getJavaClass().equals(testClass)) { + pat.configureAnnotatedType().add(SINGLETON_LITERAL); + } + } + + private class TestInstanceInjectionTarget extends ForwardingInjectionTarget { + private final InjectionTarget injectionTarget; + + TestInstanceInjectionTarget(InjectionTarget injectionTarget) { + this.injectionTarget = injectionTarget; + } + + @Override + protected InjectionTarget delegate() { + return injectionTarget; + } + + @Override + public T produce(CreationalContext creationalContext) { + return testInstance; + } + } + + void rewriteTestInstanceInjectionTarget(@Observes ProcessInjectionTarget pit) { + if (pit.getAnnotatedType().getJavaClass().equals(testClass)) { + pit.setInjectionTarget(new TestInstanceInjectionTarget(pit.getInjectionTarget())); + } + } +} diff --git a/spock/src/main/resources/META-INF/services/org.spockframework.runtime.extension.IGlobalExtension b/spock/src/main/resources/META-INF/services/org.spockframework.runtime.extension.IGlobalExtension new file mode 100644 index 00000000..ea65f914 --- /dev/null +++ b/spock/src/main/resources/META-INF/services/org.spockframework.runtime.extension.IGlobalExtension @@ -0,0 +1,2 @@ +org.jboss.weld.spock.impl.EnableWeldExtension +org.jboss.weld.spock.impl.EagerExceptionRenderer diff --git a/spock/src/test/groovy/org/jboss/weld/spock/alternative/AlternativeAsSoleBeanInSyntheticArchiveTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/alternative/AlternativeAsSoleBeanInSyntheticArchiveTest.groovy new file mode 100644 index 00000000..adf806d2 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/alternative/AlternativeAsSoleBeanInSyntheticArchiveTest.groovy @@ -0,0 +1,62 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.alternative + +import jakarta.enterprise.context.ApplicationScoped +import jakarta.inject.Inject +import org.jboss.weld.junit.MockBean +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import spock.lang.Issue +import spock.lang.Specification + +import static org.jboss.weld.spock.WeldInitiator.createWeld + +/** + * This mimics problems in issue 64, but without the need for discovery + * + * @author Björn Kautler + */ +@EnableWeld +class AlternativeAsSoleBeanInSyntheticArchiveTest extends Specification { + @WeldSetup + def weld = WeldInitiator + .from(createWeld()) + .addBeans(createSelectedAlternativeBean()) + .build() + + static createSelectedAlternativeBean() { + return MockBean + .builder() + .types(Fish) + .scope(ApplicationScoped) + .selectedAlternative(Fish) + .creating(new Fish(200)) + .build() + } + + @Inject + Fish fish + + @Issue('https://github.com/weld/weld-junit/issues/64') + def 'synthetic archive with only enabled alternative should still work'() { + expect: + fish.numberOfLegs == 200 + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/alternative/Fish.groovy b/spock/src/test/groovy/org/jboss/weld/spock/alternative/Fish.groovy new file mode 100644 index 00000000..59c7290c --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/alternative/Fish.groovy @@ -0,0 +1,33 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.alternative + +/** + * @author Björn Kautler + */ +class Fish { + private int legs + + Fish(int numberOfLegs) { + legs = numberOfLegs + } + + int getNumberOfLegs() { + return legs + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/ActivateScopesInheritanceTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/ActivateScopesInheritanceTest.groovy new file mode 100644 index 00000000..8c30610a --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/ActivateScopesInheritanceTest.groovy @@ -0,0 +1,75 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.enterprise.context.ContextNotActiveException +import jakarta.enterprise.context.ConversationScoped +import jakarta.enterprise.context.RequestScoped +import jakarta.enterprise.context.SessionScoped +import jakarta.enterprise.inject.Produces +import jakarta.enterprise.inject.spi.BeanManager +import jakarta.inject.Named +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.auto.beans.Engine +import org.jboss.weld.spock.auto.beans.V6 +import org.jboss.weld.spock.auto.beans.V8 +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +class ActivateScopesInheritanceTest extends BaseActivateScopesInheritanceTest { + @Produces + @SessionScoped + @Named("special") + V8 sessionEngine = new V8() + + @Produces + @ConversationScoped + // V6 is annotated with @ApplicationScoped, this tells the container to use producer instead + @ExcludeBean + V6 convoEngine = new V6() + + def '@ActivateScopes should activate the specified scopes'(BeanManager beanManager) { + expect: + beanManager.getContext(RequestScoped).active + beanManager.getContext(SessionScoped).active + } + + def 'Engine should be resolved to @SessionScoped V8'(@Named("special") Engine engine) { + expect: + engine.throttle == 0 + } + + def 'non-activated scopes should fail'(V6 engine) { + when: + engine.throttle + + then: + thrown(ContextNotActiveException) + } +} + +/** + * Base class for {@link ActivateScopesInheritanceTest} to test if annotations are inherited. + */ +@EnableWeld(automagic = true) +@ActivateScopes([SessionScoped, RequestScoped]) +class BaseActivateScopesInheritanceTest extends Specification { + // empty, just a base class to let annotations be inherited +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/ActivateScopesTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/ActivateScopesTest.groovy new file mode 100644 index 00000000..345e20e6 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/ActivateScopesTest.groovy @@ -0,0 +1,68 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.enterprise.context.ContextNotActiveException +import jakarta.enterprise.context.ConversationScoped +import jakarta.enterprise.context.RequestScoped +import jakarta.enterprise.context.SessionScoped +import jakarta.enterprise.inject.Produces +import jakarta.enterprise.inject.spi.BeanManager +import jakarta.inject.Named +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.auto.beans.Engine +import org.jboss.weld.spock.auto.beans.V6 +import org.jboss.weld.spock.auto.beans.V8 +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +@ActivateScopes([SessionScoped, RequestScoped]) +class ActivateScopesTest extends Specification { + @Produces + @SessionScoped + @Named('special') + V8 sessionEngine = new V8() + + @Produces + @ConversationScoped + // V6 is annotated with @ApplicationScoped, this tells the container to use this producer instead + @ExcludeBean + V6 convoEngine = new V6() + + def '@ActivateScopes should activate the specified scopes'(BeanManager beanManager) { + expect: + beanManager.getContext(RequestScoped).active + beanManager.getContext(SessionScoped).active + } + + def 'Engine should be resolved to @SessionScoped V8'(@Named("special") Engine engine) { + expect: + engine.throttle == 0 + } + + def 'non-activated scopes should fail'(V6 engine) { + when: + engine.throttle + + then: + thrown(ContextNotActiveException) + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/AddBeanClassesTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/AddBeanClassesTest.groovy new file mode 100644 index 00000000..8fb4ee3f --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/AddBeanClassesTest.groovy @@ -0,0 +1,39 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.auto.beans.Engine +import org.jboss.weld.spock.auto.beans.V8 +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +@AddBeanClasses(V8) +class AddBeanClassesTest extends Specification { + @Inject + private Engine engine + + def '@AddBeanClasses should pull in V8 to fulfill the injected Engine interface'() { + expect: + engine != null + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/AddDecoratorTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/AddDecoratorTest.groovy new file mode 100644 index 00000000..b415984f --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/AddDecoratorTest.groovy @@ -0,0 +1,42 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.auto.interceptorAndDecorator.DecoratedBean +import org.jboss.weld.spock.auto.interceptorAndDecorator.TestDecorator +import spock.lang.Specification + +/** + * Test that you can add decorator class and enable it (no need for priority) via annotation. + * + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +@AddEnabledDecorators(TestDecorator) +class AddDecoratorTest extends Specification { + @Inject + DecoratedBean bean + + def 'bean should be decorated'() { + expect: + bean != null + bean.ping() == TestDecorator.toString() + DecoratedBean.toString() + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/AddExtensionsTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/AddExtensionsTest.groovy new file mode 100644 index 00000000..0b2c5394 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/AddExtensionsTest.groovy @@ -0,0 +1,34 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.auto.extension.AddedExtension +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +@AddExtensions(AddedExtension) +class AddExtensionsTest extends Specification { + def '@AddExtensions should add the specified extensions'() { + expect: + AddedExtension.enabled + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/AddInterceptorTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/AddInterceptorTest.groovy new file mode 100644 index 00000000..4d266638 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/AddInterceptorTest.groovy @@ -0,0 +1,41 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.auto.interceptorAndDecorator.InterceptedBean +import org.jboss.weld.spock.auto.interceptorAndDecorator.TestInterceptor +import spock.lang.Specification + +/** + * Test that you can add interceptor class and enable it (no need for priority) via annotation. + * + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +@AddEnabledInterceptors(TestInterceptor) +class AddInterceptorTest extends Specification { + @Inject + InterceptedBean bean + + def 'bean should be intercepted'() { + expect: + bean.ping() == TestInterceptor.toString() + InterceptedBean.toString() + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/AddPackagesTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/AddPackagesTest.groovy new file mode 100644 index 00000000..8c6954d8 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/AddPackagesTest.groovy @@ -0,0 +1,39 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.auto.beans.Engine +import org.jboss.weld.spock.auto.beans.V8 +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +@AddPackages(value = Engine, recursively = false) +class AddPackagesTest extends Specification { + @Inject + private V8 engine + + def '@AddPackages should pull in V8 to fulfill the injected Engine interface'() { + expect: + engine != null + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/AnnotationsInheritanceTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/AnnotationsInheritanceTest.groovy new file mode 100644 index 00000000..047cee87 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/AnnotationsInheritanceTest.groovy @@ -0,0 +1,106 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.auto.beans.Engine +import org.jboss.weld.spock.auto.beans.V8 +import org.jboss.weld.spock.auto.extension.AddedExtension +import org.jboss.weld.spock.auto.interceptorAndDecorator.DecoratedBean +import org.jboss.weld.spock.auto.interceptorAndDecorator.InterceptedBean +import org.jboss.weld.spock.auto.interceptorAndDecorator.TestDecorator +import org.jboss.weld.spock.auto.interceptorAndDecorator.TestInterceptor +import spock.lang.Specification + +/** + * Tests the inheritance of "Weld-Spock" annotations from test parent classes. + * + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +@AddBeanClasses(V8) +class BaseAddBeanClassesTest extends Specification { +} + +class AnnotationsInheritanceAddBeanClassesTest extends BaseAddBeanClassesTest { + @Inject + private Engine engine + + def '@AddBeanClasses should pull in V8 to fulfill the injected Engine interface'() { + expect: + engine != null + } +} + +@EnableWeld(automagic = true) +@AddEnabledDecorators(TestDecorator) +class BaseAddDecoratorTest extends Specification { +} + +class AnnotationsInheritanceAddDecoratorTest extends BaseAddDecoratorTest { + @Inject + DecoratedBean bean + + def 'bean should be decorated'() { + expect: + bean.ping() == TestDecorator.toString() + DecoratedBean.toString() + } +} + +@EnableWeld(automagic = true) +@AddExtensions(AddedExtension) +class BaseAddExtensionsTest extends Specification { +} + +class AnnotationsInheritanceAddExtensionsTest extends BaseAddExtensionsTest { + def '@AddExtensions should add the specified extensions'() { + expect: + AddedExtension.enabled + } +} + +@EnableWeld(automagic = true) +@AddEnabledInterceptors(TestInterceptor) +class BaseAddInterceptorTest extends Specification { +} + +class AnnotationsInheritanceAddInterceptorTest extends BaseAddInterceptorTest { + @Inject + InterceptedBean bean + + def 'bean should be intercepted'() { + expect: + bean.ping() == TestInterceptor.toString() + InterceptedBean.toString() + } +} + +@EnableWeld(automagic = true) +@AddPackages(value = Engine, recursively = false) +class BaseAddPackagesTest { +} + +class AnnotationsInheritanceAddPackagesTest extends BaseAddPackagesTest { + @Inject + private V8 engine + + def '@AddPackages should pull in V8 (without bean defining annotation) to fulfill the injected Engine interface'() { + expect: + engine != null + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/AutoConfigWithWeldSetupTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/AutoConfigWithWeldSetupTest.groovy new file mode 100644 index 00000000..eaa28d8a --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/AutoConfigWithWeldSetupTest.groovy @@ -0,0 +1,60 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import org.jboss.weld.spock.util.EmbeddedSpecRunnerWrapper +import org.spockframework.runtime.InvalidSpecException +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +class AutoConfigWithWeldSetupTest extends Specification { + def '@WeldSetup should not be compatible with automagic mode'() { + given: + def runner = new EmbeddedSpecRunnerWrapper() + runner.addClassImport(EnableWeld) + runner.addClassImport(WeldSetup) + runner.addClassImport(WeldInitiator) + runner.addClassMemberImport(WeldInitiator) + + when: + runner.runWithImports ''' + @EnableWeld(automagic = true) + class Foo extends Specification { + @WeldSetup + def weld = WeldInitiator.of(createWeld()) + + def bar() { + expect: + 'IllegalStateException expected' == 'before feature method is entered' + } + } + ''' + + then: + InvalidSpecException ise = thrown() + ise.message == ''' + When using automagic mode, no @WeldSetup annotated field should be present! Fields found: + Field 'weld' with type class java.lang.Object which is in Foo + '''.stripIndent(true).trim() + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/BasicAutoConfigTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/BasicAutoConfigTest.groovy new file mode 100644 index 00000000..9975d52c --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/BasicAutoConfigTest.groovy @@ -0,0 +1,42 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.basic.Foo +import org.jboss.weld.spock.explicitInjection.Bar +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +class BasicAutoConfigTest extends Specification { + @Inject + private Foo foo + + @Inject + private Bar bar + + def 'the injected Foo and Bar should be automatically included in container with no configuration'() { + expect: + bar != null + foo.bar == 'baz' + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/ExcludeBeanClassesDepsTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/ExcludeBeanClassesDepsTest.groovy new file mode 100644 index 00000000..9e2230b2 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/ExcludeBeanClassesDepsTest.groovy @@ -0,0 +1,46 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.enterprise.inject.Produces +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.basic.unsatisfied.FooDeps +import org.jboss.weld.spock.basic.unsatisfied.SomeFooDeps +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +@AddBeanClasses(SomeFooDeps) +@ExcludeBeanClasses(FooDeps) +class ExcludeBeanClassesDepsTest extends Specification { + /** + * FooDeps injects the Baz bean which has an unsatisfied dependency "bar-value". Excluding FooDeps should ensure + * that its specific dependencies are not included via scanning and therefore don't need to be provided for + * testing. + */ + + @Produces + FooDeps fakeFooDeps = new FooDeps() + + def '@ExcludeBeanClasses should exclude any specific dependencies of the excluded classes'(FooDeps myFooDeps) { + expect: + myFooDeps != null + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/ExcludeBeanClassesTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/ExcludeBeanClassesTest.groovy new file mode 100644 index 00000000..975fd0a8 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/ExcludeBeanClassesTest.groovy @@ -0,0 +1,40 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.enterprise.inject.Produces +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.basic.Foo +import org.jboss.weld.spock.basic.SomeFoo +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +@AddBeanClasses(SomeFoo) +@ExcludeBeanClasses(Foo) +class ExcludeBeanClassesTest extends Specification { + @Produces + static Foo fakeFoo = new Foo('non-baz') + + def '@ExcludeBeanClasses should exclude the specified classes'(Foo myFoo) { + expect: + myFoo.bar == 'non-baz' + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/ExcludeBeanDepsTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/ExcludeBeanDepsTest.groovy new file mode 100644 index 00000000..2a802cd8 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/ExcludeBeanDepsTest.groovy @@ -0,0 +1,46 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.enterprise.inject.Produces +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.basic.unsatisfied.FooDeps +import org.jboss.weld.spock.basic.unsatisfied.SomeFooDeps +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +@AddBeanClasses(SomeFooDeps) +class ExcludeBeanDepsTest extends Specification { + /** + * FooDeps injects the Baz bean which has an unsatisfied dependency "bar-value". Excluding FooDeps should ensure + * that its specific dependencies are not included via scanning and therefore don't need to be provided for + * testing. + */ + + @Produces + @ExcludeBean + FooDeps fakeFooDeps = new FooDeps() + + def '@ExcludeBean should exclude any specific dependencies of the excluded class'(FooDeps myFooDeps) { + expect: + myFooDeps != null + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/ExcludeBeanHierarchyTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/ExcludeBeanHierarchyTest.groovy new file mode 100644 index 00000000..285328c4 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/ExcludeBeanHierarchyTest.groovy @@ -0,0 +1,41 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.enterprise.inject.Produces +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.basic.Foo +import org.jboss.weld.spock.basic.IFoo +import org.jboss.weld.spock.basic.SomeIFoo +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +@AddBeanClasses(SomeIFoo) +class ExcludeBeanHierarchyTest extends Specification { + @Produces + @ExcludeBean + IFoo fakeFoo = new Foo('non-baz') + + def '@ExcludeBean should exclude all beans in implied hierarchy'(IFoo myIFoo) { + expect: + myIFoo.bar == 'non-baz' + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/ExcludeBeanTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/ExcludeBeanTest.groovy new file mode 100644 index 00000000..bd63c73e --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/ExcludeBeanTest.groovy @@ -0,0 +1,40 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.enterprise.inject.Produces +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.basic.Foo +import org.jboss.weld.spock.basic.SomeFoo +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +@AddBeanClasses(SomeFoo) +class ExcludeBeanTest extends Specification { + @Produces + @ExcludeBean + Foo fakeFoo = new Foo('non-baz') + + def '@ExcludeBean should exclude the implied bean class'(Foo myFoo) { + expect: + myFoo.bar == 'non-baz' + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/ExplicitParametersAutoConfigTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/ExplicitParametersAutoConfigTest.groovy new file mode 100644 index 00000000..57bb3ce7 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/ExplicitParametersAutoConfigTest.groovy @@ -0,0 +1,39 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.enterprise.inject.Default +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.basic.Foo +import org.jboss.weld.spock.explicitInjection.Bar +import org.jboss.weld.spock.explicitInjection.Custom +import org.jboss.weld.spock.explicitInjection.CustomExtension +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld(automagic = true, explicitParamInjection = true) +class ExplicitParametersAutoConfigTest extends Specification { + @Custom + def 'the parameter Foo should be automatically included in container and Bar should come from @Custom'(@Default Foo foo, Bar bar) { + expect: + bar.ping() == CustomExtension.simpleName + foo.bar == 'baz' + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/InheritedInjectedTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/InheritedInjectedTest.groovy new file mode 100644 index 00000000..6ed7bdcc --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/InheritedInjectedTest.groovy @@ -0,0 +1,62 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.enterprise.context.Dependent +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@Dependent +class InheritedInjectedTestFoo { +} + +@EnableWeld(automagic = true) +class InheritedInjectedTestBaseClass extends Specification { + @Inject + InheritedInjectedTestFoo foo +} + +class InjectIntoInheritedFieldsFromTestBaseClassTest extends InheritedInjectedTestBaseClass { + def 'inherited fields of a super spec should be injected'() { + expect: + foo != null + } +} + +@Dependent +class SubClass extends InheritedInjectedTestBaseClass { +} + +@EnableWeld(automagic = true) +class InjectIntoInheritedFieldsFromBeanBaseClassTest extends Specification { + @Inject + SubClass inheritsInjected + + /** + * Injection of {@link #inheritsInjected} requires {@link InheritedInjectedTestFoo} + * having been identified and added as a bean class to Weld. + */ + def 'inherited field in bean should be injected'() { + expect: + inheritsInjected?.foo != null + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/InheritedProducerFieldTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/InheritedProducerFieldTest.groovy new file mode 100644 index 00000000..8aeba0dc --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/InheritedProducerFieldTest.groovy @@ -0,0 +1,52 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.enterprise.context.Dependent +import jakarta.enterprise.inject.Produces +import jakarta.enterprise.inject.spi.BeanManager +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@Dependent +class InheritedProducerFieldTestFoo { +} + +class InheritedProducerFieldTestBaseClass { + @Produces + InheritedProducerFieldTestFoo baseFooProducer = new InheritedProducerFieldTestFoo() +} + +@Dependent +class InheritedProducerFieldTestSubClass extends InheritedProducerFieldTestBaseClass { +} + +@EnableWeld(automagic = true) +class DontAddBeanClassesFromFieldsInheritedFromBeanBaseClassTest extends Specification { + @Inject + InheritedProducerFieldTestSubClass subClass + + def 'inherited producer field type from bean base class should not be added to the container'(BeanManager beanManager) { + expect: + beanManager.getBeans(InheritedProducerFieldTestFoo).size() == 0 + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/InheritedProducerMethodTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/InheritedProducerMethodTest.groovy new file mode 100644 index 00000000..1e495126 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/InheritedProducerMethodTest.groovy @@ -0,0 +1,54 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.enterprise.context.Dependent +import jakarta.enterprise.inject.Produces +import jakarta.enterprise.inject.spi.BeanManager +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@Dependent +class InheritedProducerMethodTestFoo { +} + +class InheritedProducerMethodTestBaseClass { + @Produces + InheritedProducerMethodTestFoo baseFooProducer() { + new InheritedProducerMethodTestFoo() + } +} + +@Dependent +class InheritedProducerMethodTestSubClass extends InheritedProducerMethodTestBaseClass { +} + +@EnableWeld(automagic = true) +class DontAddBeanClassesFromMethodInheritedFromBeanBaseClassTest extends Specification { + @Inject + InheritedProducerMethodTestSubClass subClass + + void 'inherited producer method return type from bean base class should not be added to the container'(BeanManager beanManager) { + expect: + beanManager.getBeans(InheritedProducerMethodTestFoo).size() == 0 + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/InjectInstanceTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/InjectInstanceTest.groovy new file mode 100644 index 00000000..a6cddb08 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/InjectInstanceTest.groovy @@ -0,0 +1,42 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.enterprise.context.Dependent +import jakarta.enterprise.inject.Instance +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +class InjectInstanceTest extends Specification { + @Dependent + static class Foo { + } + + @Inject + Instance fooInstance + + def 'injecting Instance should work properly'() { + expect: + fooInstance.get() != null + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/InjectParameterizedInstanceTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/InjectParameterizedInstanceTest.groovy new file mode 100644 index 00000000..4b83d8e7 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/InjectParameterizedInstanceTest.groovy @@ -0,0 +1,42 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.enterprise.context.Dependent +import jakarta.enterprise.inject.Instance +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +class InjectParameterizedInstanceTest extends Specification { + @Dependent + static class Foo { + } + + @Inject + Instance> fooInstance + + def 'injecting Instance of parameterized type should work properly'() { + expect: + fooInstance.get() != null + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/InjectParameterizedTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/InjectParameterizedTest.groovy new file mode 100644 index 00000000..0faa6ae9 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/InjectParameterizedTest.groovy @@ -0,0 +1,41 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.enterprise.context.Dependent +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +class InjectParameterizedTest extends Specification { + @Dependent + static class Foo { + } + + @Inject + Foo foo + + def 'injecting parameterized type should work properly'() { + expect: + foo != null + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/ParametersAutoConfigTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/ParametersAutoConfigTest.groovy new file mode 100644 index 00000000..b411e2e0 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/ParametersAutoConfigTest.groovy @@ -0,0 +1,36 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.basic.Foo +import org.jboss.weld.spock.explicitInjection.Bar +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +class ParametersAutoConfigTest extends Specification { + def 'the parameters Foo and Bar should be automatically included in container with no configuration'(Foo foo, Bar bar) { + expect: + bar != null + bar.ping() == null + foo?.bar == 'baz' + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/ProducerMethodParametersScanningTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/ProducerMethodParametersScanningTest.groovy new file mode 100644 index 00000000..2476a4eb --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/ProducerMethodParametersScanningTest.groovy @@ -0,0 +1,54 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.enterprise.context.Dependent +import jakarta.enterprise.inject.Produces +import jakarta.inject.Named +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.auto.beans.Engine +import org.jboss.weld.spock.auto.beans.V6 +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +class ProducerMethodParametersScanningTest extends Specification { + @Produces + @Named('custom') + @Dependent + Engine getEngine(V6 v6) { + new Engine() { + @Override + int getThrottle() { + v6.throttle + } + + @Override + void setThrottle(int value) { + v6.throttle = value + } + } + } + + def 'parameters of producer methods should be automatically added to container'(@Named('custom') Engine engine) { + expect: + engine != null + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/ProducesBeforeTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/ProducesBeforeTest.groovy new file mode 100644 index 00000000..a7608fde --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/ProducesBeforeTest.groovy @@ -0,0 +1,48 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.enterprise.context.Dependent +import jakarta.enterprise.inject.Produces +import jakarta.inject.Named +import org.jboss.weld.spock.EnableWeld +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +class ProducesBeforeTest extends Specification { + private Integer requiredValue + + def setup() { + requiredValue = 10 + } + + @Produces + @Dependent + @Named("computed") + Integer provideComputedValue() { + return requiredValue * 10 + } + + def 'setup should run before any @Produces methods/fields are interrogated'(@Named("computed") Integer computed) { + expect: + computed != null + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/ScannedClassesAreNotForcedBeansTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/ScannedClassesAreNotForcedBeansTest.groovy new file mode 100644 index 00000000..13c391da --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/ScannedClassesAreNotForcedBeansTest.groovy @@ -0,0 +1,51 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.enterprise.inject.Produces +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.auto.beans.unsatisfied.InjectedV8NoAnnotation +import org.jboss.weld.spock.auto.beans.unsatisfied.V8NoAnnotation +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +@AddBeanClasses(InjectedV8NoAnnotation) +class ScannedClassesAreNotForcedBeansTest extends Specification { + /** + * V8 is *not* a "bean" class, in that it has no bean defining annotation. To satisfy + * a dependency on it, a producer method or a reference in an @AddBeanClasses annotation + * is required. + *

+ * This test ensures that as V8 is discovered via class scanning it is not automatically + * added as a bean class. If it was added that way, the bean class and producer method would + * create an ambiguous injection case for V8. + * + * NOTE: This case only tests for classes found as non-parameters (e.g. injected fields) + */ + + @Produces + private V8NoAnnotation engine = new V8NoAnnotation() + + def 'V8NoAnnotation should not be ambiguous for not being incorrectly identified as a bean class'(V8NoAnnotation engine) { + expect: + engine != null + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/ScannedParameterClassesAreNotForcedBeansTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/ScannedParameterClassesAreNotForcedBeansTest.groovy new file mode 100644 index 00000000..80f1d15d --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/ScannedParameterClassesAreNotForcedBeansTest.groovy @@ -0,0 +1,52 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto + +import jakarta.enterprise.inject.Produces +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.auto.beans.unsatisfied.ConstructedV8NoAnnotation +import org.jboss.weld.spock.auto.beans.unsatisfied.V8NoAnnotation +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +@AddBeanClasses(ConstructedV8NoAnnotation) +class ScannedParameterClassesAreNotForcedBeansTest extends Specification { + /** + * V8NoAnnotation is *not* a "bean" class, in that it has no bean defining annotation. To satisfy + * a dependency on it, a producer method or a reference in an @AddBeanClasses annotation + * is required. + *

+ * This test ensures that as V8NoAnnotation is discovered via class scanning it is not automatically + * added as a bean class. If it was added that way, the bean class and producer method would + * create an ambiguous injection case for V8. + * + * NOTE: This case only tests for classes found from parameters (e.g. constructor injection + * parameters) + */ + + @Produces + private V8NoAnnotation engine = new V8NoAnnotation() + + def 'V8NoAnnotation should not be ambiguous for not being incorrectly identified as a bean class from parameter'(V8NoAnnotation engine) { + expect: + engine != null + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/alternativeStereotype/EnableAlternativeStereotypeInheritanceTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/alternativeStereotype/EnableAlternativeStereotypeInheritanceTest.groovy new file mode 100644 index 00000000..eb8b7f39 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/alternativeStereotype/EnableAlternativeStereotypeInheritanceTest.groovy @@ -0,0 +1,45 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.alternativeStereotype + +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.auto.AddBeanClasses +import org.jboss.weld.spock.auto.EnableAlternativeStereotypes +import spock.lang.Specification + +/** + * Tests that annotation which enables alternative stereotype can be inherited + * + * @author Björn Kautler + */ +class EnableAlternativeStereotypeInheritanceTest extends BaseAlternativeStereotypeInheritanceTest { + @Inject + Foo foo + + def 'inheritance for alternative stereotype annotation should work properly'() { + expect: + foo.ping() == FooAlternative.simpleName + } +} + +@EnableWeld(automagic = true) +@AddBeanClasses([Foo, FooAlternative]) +@EnableAlternativeStereotypes(SomeStereotype) +class BaseAlternativeStereotypeInheritanceTest extends Specification { +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/alternativeStereotype/EnableAlternativeStereotypeTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/alternativeStereotype/EnableAlternativeStereotypeTest.groovy new file mode 100644 index 00000000..e5a1337d --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/alternativeStereotype/EnableAlternativeStereotypeTest.groovy @@ -0,0 +1,42 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.alternativeStereotype + +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.auto.AddBeanClasses +import org.jboss.weld.spock.auto.EnableAlternativeStereotypes +import spock.lang.Specification + +/** + * Tests that alternative stereotype can be enabled via annotation. + * + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +@AddBeanClasses([Foo, FooAlternative]) +@EnableAlternativeStereotypes(SomeStereotype) +class EnableAlternativeStereotypeTest extends Specification { + @Inject + Foo foo + + def 'enabled alternative stereotype should be enabled'() { + expect: + foo.ping() == FooAlternative.simpleName + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/alternativeStereotype/Foo.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/alternativeStereotype/Foo.groovy new file mode 100644 index 00000000..c809bf1d --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/alternativeStereotype/Foo.groovy @@ -0,0 +1,30 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.alternativeStereotype + +import jakarta.enterprise.context.ApplicationScoped + +/** + * @author Björn Kautler + */ +@ApplicationScoped +class Foo { + String ping() { + Foo.simpleName + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/alternativeStereotype/FooAlternative.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/alternativeStereotype/FooAlternative.groovy new file mode 100644 index 00000000..87e814d7 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/alternativeStereotype/FooAlternative.groovy @@ -0,0 +1,31 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.alternativeStereotype + +import jakarta.enterprise.context.ApplicationScoped + +/** + * @author Björn Kautler + */ +@SomeStereotype +@ApplicationScoped +class FooAlternative extends Foo { + String ping() { + FooAlternative.simpleName + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/alternativeStereotype/SomeStereotype.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/alternativeStereotype/SomeStereotype.groovy new file mode 100644 index 00000000..7a6f089e --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/alternativeStereotype/SomeStereotype.groovy @@ -0,0 +1,37 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.alternativeStereotype + +import java.lang.annotation.Retention +import java.lang.annotation.Target + +import jakarta.enterprise.inject.Alternative +import jakarta.enterprise.inject.Stereotype + +import static java.lang.annotation.ElementType.TYPE +import static java.lang.annotation.RetentionPolicy.RUNTIME + +/** + * @author Björn Kautler + */ +@Stereotype +@Alternative +@Retention(RUNTIME) +@Target(TYPE) +@interface SomeStereotype { +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/alternatives/EnableAlternativeTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/alternatives/EnableAlternativeTest.groovy new file mode 100644 index 00000000..873d9e55 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/alternatives/EnableAlternativeTest.groovy @@ -0,0 +1,42 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.alternatives + +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.auto.AddBeanClasses +import org.jboss.weld.spock.auto.EnableAlternatives +import spock.lang.Specification + +/** + * Tests that @EnableAlternative works + * + * @author Björn Kautler + */ +@EnableWeld(automagic = true) +@EnableAlternatives(FooAlternative) +@AddBeanClasses([Foo, FooAlternative]) +class EnableAlternativeTest extends Specification { + @Inject + Foo foo + + def 'alternative should be enabled'() { + expect: + foo.ping() == FooAlternative.simpleName + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/alternatives/EnableAlternativesInheritanceTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/alternatives/EnableAlternativesInheritanceTest.groovy new file mode 100644 index 00000000..9d4a599a --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/alternatives/EnableAlternativesInheritanceTest.groovy @@ -0,0 +1,46 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.alternatives + +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.auto.AddBeanClasses +import org.jboss.weld.spock.auto.EnableAlternatives +import spock.lang.Specification + +/** + * Extends {@link BaseEnableAlternativeTest} hence inheriting the annotations. This tests that alternative enablement will be + * inherited. + * + * @author Björn Kautler + */ +class EnableAlternativesInheritanceTest extends BaseEnableAlternativeTest { + @Inject + Foo foo + + def 'alternative enablement should be inherited'() { + expect: + foo.ping() == FooAlternative.simpleName + } +} + +@EnableWeld(automagic = true) +@AddBeanClasses([Foo, FooAlternative]) +@EnableAlternatives(FooAlternative) +class BaseEnableAlternativeTest extends Specification { +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/alternatives/Foo.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/alternatives/Foo.groovy new file mode 100644 index 00000000..e44815e4 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/alternatives/Foo.groovy @@ -0,0 +1,30 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.alternatives + +import jakarta.enterprise.context.ApplicationScoped + +/** + * @author Björn Kautler + */ +@ApplicationScoped +class Foo { + String ping() { + Foo.simpleName + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/alternatives/FooAlternative.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/alternatives/FooAlternative.groovy new file mode 100644 index 00000000..1510b46a --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/alternatives/FooAlternative.groovy @@ -0,0 +1,32 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.alternatives + +import jakarta.enterprise.context.ApplicationScoped +import jakarta.enterprise.inject.Alternative + +/** + * @author Björn Kautler + */ +@Alternative +@ApplicationScoped +class FooAlternative extends Foo { + String ping() { + FooAlternative.simpleName + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/beans/Engine.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/beans/Engine.groovy new file mode 100644 index 00000000..15129669 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/beans/Engine.groovy @@ -0,0 +1,27 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.beans + +/** + * @author Björn Kautler + */ +interface Engine { + int getThrottle() + + void setThrottle(int value) +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/beans/V6.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/beans/V6.groovy new file mode 100644 index 00000000..aa63d8ca --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/beans/V6.groovy @@ -0,0 +1,37 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.beans + +import jakarta.enterprise.context.ApplicationScoped + +/** + * @author Björn Kautler + */ +@ApplicationScoped +class V6 implements Engine, Serializable { + private int throttle = 0 + + int getThrottle() { + return throttle + } + + @Override + void setThrottle(int throttle) { + this.throttle = throttle + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/beans/V8.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/beans/V8.groovy new file mode 100644 index 00000000..151d9162 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/beans/V8.groovy @@ -0,0 +1,37 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.beans + +import jakarta.enterprise.context.Dependent + +/** + * @author Björn Kautler + */ +@Dependent +class V8 implements Engine, Serializable { + private int throttle = 0 + + int getThrottle() { + return throttle + } + + @Override + void setThrottle(int throttle) { + this.throttle = throttle + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/beans/unsatisfied/ConstructedV8NoAnnotation.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/beans/unsatisfied/ConstructedV8NoAnnotation.groovy new file mode 100644 index 00000000..9ba3c3eb --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/beans/unsatisfied/ConstructedV8NoAnnotation.groovy @@ -0,0 +1,34 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.beans.unsatisfied + +import jakarta.enterprise.context.ApplicationScoped +import jakarta.inject.Inject + +/** + * @author Björn Kautler + */ +@ApplicationScoped +class ConstructedV8NoAnnotation { + private V8NoAnnotation engine + + @Inject + ConstructedV8NoAnnotation(V8NoAnnotation engine) { + this.engine = engine + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/beans/unsatisfied/InjectedV8NoAnnotation.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/beans/unsatisfied/InjectedV8NoAnnotation.groovy new file mode 100644 index 00000000..000baa66 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/beans/unsatisfied/InjectedV8NoAnnotation.groovy @@ -0,0 +1,30 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.beans.unsatisfied + +import jakarta.enterprise.context.ApplicationScoped +import jakarta.inject.Inject + +/** + * @author Björn Kautler + */ +@ApplicationScoped +class InjectedV8NoAnnotation { + @Inject + V8NoAnnotation v8 +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/beans/unsatisfied/V8NoAnnotation.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/beans/unsatisfied/V8NoAnnotation.groovy new file mode 100644 index 00000000..5bdb0ab1 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/beans/unsatisfied/V8NoAnnotation.groovy @@ -0,0 +1,37 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.beans.unsatisfied + +import org.jboss.weld.spock.auto.beans.Engine + +/** + * @author Björn Kautler + */ +// NOTE - deliberately missing bean defining annotation +class V8NoAnnotation implements Engine, Serializable { + private int throttle = 0 + + int getThrottle() { + return throttle + } + + @Override + void setThrottle(int throttle) { + this.throttle = throttle + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/extension/AddedExtension.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/extension/AddedExtension.groovy new file mode 100644 index 00000000..4a57c723 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/extension/AddedExtension.groovy @@ -0,0 +1,37 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.extension + +import jakarta.enterprise.event.Observes +import jakarta.enterprise.inject.spi.AfterBeanDiscovery +import jakarta.enterprise.inject.spi.Extension + +/** + * @author Björn Kautler + */ +class AddedExtension implements Extension { + private static boolean enabled = false + + void observeABD(@Observes AfterBeanDiscovery abd) { + enabled = true + } + + static boolean isEnabled() { + enabled + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/interceptorAndDecorator/DecoratedBean.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/interceptorAndDecorator/DecoratedBean.groovy new file mode 100644 index 00000000..deefb0b2 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/interceptorAndDecorator/DecoratedBean.groovy @@ -0,0 +1,31 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.interceptorAndDecorator + +import jakarta.enterprise.context.Dependent + +/** + * @author Björn Kautler + */ +@Dependent +class DecoratedBean implements DecoratedBeanInterface { + @Override + String ping() { + DecoratedBean.toString() + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/interceptorAndDecorator/DecoratedBeanInterface.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/interceptorAndDecorator/DecoratedBeanInterface.groovy new file mode 100644 index 00000000..391f731f --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/interceptorAndDecorator/DecoratedBeanInterface.groovy @@ -0,0 +1,25 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.interceptorAndDecorator + +/** + * @author Björn Kautler + */ +interface DecoratedBeanInterface { + String ping() +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/interceptorAndDecorator/InterceptedBean.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/interceptorAndDecorator/InterceptedBean.groovy new file mode 100644 index 00000000..0ac9d2ef --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/interceptorAndDecorator/InterceptedBean.groovy @@ -0,0 +1,31 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.interceptorAndDecorator + +import jakarta.enterprise.context.Dependent + +/** + * @author Björn Kautler + */ +@Dependent +class InterceptedBean { + @TestInterceptorBinding + String ping() { + InterceptedBean.toString() + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/interceptorAndDecorator/TestDecorator.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/interceptorAndDecorator/TestDecorator.groovy new file mode 100644 index 00000000..4b31cb44 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/interceptorAndDecorator/TestDecorator.groovy @@ -0,0 +1,40 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.interceptorAndDecorator + +import jakarta.decorator.Decorator +import jakarta.decorator.Delegate +import jakarta.enterprise.inject.Typed +import jakarta.inject.Inject + +/** + * @author Björn Kautler + */ +@Decorator +// work-around for https://issues.redhat.com/browse/WELD-2713 +@Typed(DecoratedBeanInterface) +class TestDecorator implements DecoratedBeanInterface { + @Inject + @Delegate + DecoratedBeanInterface delegate + + @Override + String ping() { + TestDecorator.toString() + delegate.ping() + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/interceptorAndDecorator/TestInterceptor.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/interceptorAndDecorator/TestInterceptor.groovy new file mode 100644 index 00000000..b1cafb96 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/interceptorAndDecorator/TestInterceptor.groovy @@ -0,0 +1,34 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.interceptorAndDecorator + +import jakarta.interceptor.AroundInvoke +import jakarta.interceptor.Interceptor +import jakarta.interceptor.InvocationContext + +/** + * @author Björn Kautler + */ +@Interceptor +@TestInterceptorBinding +class TestInterceptor { + @AroundInvoke + Object intercept(InvocationContext ctx) throws Exception { + TestInterceptor.toString() + ctx.proceed() + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/auto/interceptorAndDecorator/TestInterceptorBinding.groovy b/spock/src/test/groovy/org/jboss/weld/spock/auto/interceptorAndDecorator/TestInterceptorBinding.groovy new file mode 100644 index 00000000..435f25bb --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/auto/interceptorAndDecorator/TestInterceptorBinding.groovy @@ -0,0 +1,36 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.auto.interceptorAndDecorator + +import java.lang.annotation.Retention +import java.lang.annotation.Target + +import jakarta.interceptor.InterceptorBinding + +import static java.lang.annotation.ElementType.METHOD +import static java.lang.annotation.ElementType.TYPE +import static java.lang.annotation.RetentionPolicy.RUNTIME + +/** + * @author Björn Kautler + */ +@InterceptorBinding +@Retention(RUNTIME) +@Target([TYPE, METHOD]) +@interface TestInterceptorBinding { +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/basic/BeanManagerTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/basic/BeanManagerTest.groovy new file mode 100644 index 00000000..7fd969d5 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/basic/BeanManagerTest.groovy @@ -0,0 +1,38 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.basic + +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld +class BeanManagerTest extends Specification { + + @WeldSetup + def weld = WeldInitiator.of(Foo) + + def 'BeanManager should be able to resolve added bean'() { + expect: + weld.beanManager.getBeans(Foo).size() == 1 + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/basic/ContainerNotRunningTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/basic/ContainerNotRunningTest.groovy new file mode 100644 index 00000000..f8ae9c1c --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/basic/ContainerNotRunningTest.groovy @@ -0,0 +1,45 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.basic + +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import spock.lang.Specification + +import static org.jboss.weld.spock.WeldInitiator.createWeld + +/** + * @author Björn Kautler + */ +@EnableWeld +class ContainerNotRunningTest extends Specification { + @WeldSetup + def weld = WeldInitiator.of(createWeld().beanClasses(Foo)) + + def 'Weld should throw IllegalStateException after container was shut down'() { + given: 'Shutdown container manually' + weld.shutdown() + + when: + weld.select(Foo).get() + + then: + thrown(IllegalStateException) + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/basic/CustomWeldTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/basic/CustomWeldTest.groovy new file mode 100644 index 00000000..5492cf48 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/basic/CustomWeldTest.groovy @@ -0,0 +1,41 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.basic + +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import spock.lang.Specification + +import static org.jboss.weld.spock.WeldInitiator.createWeld + +/** + * @author Björn Kautler + */ +@EnableWeld +class CustomWeldTest extends Specification { + @WeldSetup + def weld = WeldInitiator.of(createWeld() + .alternatives(FooAlternative) + .beanClasses(Foo, FooAlternative)) + + def 'Weld should select registered alternative'() { + expect: + weld.select(Foo).get().bar == 'BAZ' + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/basic/EnableWeldTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/basic/EnableWeldTest.groovy new file mode 100644 index 00000000..769fa026 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/basic/EnableWeldTest.groovy @@ -0,0 +1,37 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.basic + +import jakarta.enterprise.inject.spi.BeanManager +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld +class EnableWeldTest extends Specification { + @Inject + BeanManager beanManager + + def '@EnableWeld should initialize the Weld CDI container'() { + expect: + beanManager != null + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/basic/Foo.groovy b/spock/src/test/groovy/org/jboss/weld/spock/basic/Foo.groovy new file mode 100644 index 00000000..f5da68e9 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/basic/Foo.groovy @@ -0,0 +1,46 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.basic + +import jakarta.annotation.PostConstruct +import jakarta.enterprise.context.ApplicationScoped + +/** + * @author Björn Kautler + */ +@ApplicationScoped +class Foo implements IFoo { + + private String bar + + Foo() { + } + + Foo(String bar) { + this.bar = bar + } + + @PostConstruct + void init() { + bar = 'baz' + } + + String getBar() { + return bar + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/basic/FooAlternative.groovy b/spock/src/test/groovy/org/jboss/weld/spock/basic/FooAlternative.groovy new file mode 100644 index 00000000..c902ea10 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/basic/FooAlternative.groovy @@ -0,0 +1,31 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.basic + +import jakarta.enterprise.inject.Alternative + +/** + * @author Björn Kautler + */ +@Alternative +class FooAlternative extends Foo { + @Override + String getBar() { + return super.bar.toUpperCase() + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/basic/IFoo.groovy b/spock/src/test/groovy/org/jboss/weld/spock/basic/IFoo.groovy new file mode 100644 index 00000000..3f7cfb25 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/basic/IFoo.groovy @@ -0,0 +1,25 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.basic + +/** + * @author Björn Kautler + */ +interface IFoo { + String getBar() +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/basic/SimpleTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/basic/SimpleTest.groovy new file mode 100644 index 00000000..139a20d4 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/basic/SimpleTest.groovy @@ -0,0 +1,67 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.basic + +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import org.jboss.weld.spock.ofpackage.Alpha +import spock.lang.Issue +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld +class SimpleTest extends Specification { + @WeldSetup + def weld = WeldInitiator.of(Foo) + + def 'test Foo A'() { + expect: + weld.select(Foo).get().bar == 'baz' + !weld.select(Alpha).resolvable + } + + @Issue('https://github.com/weld/weld-junit/issues/19') + void 'test Foo B'() { + expect: + weld.select(Foo).get().bar == 'baz' + !weld.select(Alpha).resolvable + } + + def 'manual non-contextual injection should work properly'() { + given: + def sut = new NonContextual() + + when: + def contextReleaser = weld.injectNonContextual(sut) + + then: + sut.foo.bar == 'baz' + + cleanup: + contextReleaser.close() + } + + private static class NonContextual { + @Inject + private Foo foo + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/basic/SomeFoo.groovy b/spock/src/test/groovy/org/jboss/weld/spock/basic/SomeFoo.groovy new file mode 100644 index 00000000..9a298bc9 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/basic/SomeFoo.groovy @@ -0,0 +1,30 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.basic + +import jakarta.enterprise.context.ApplicationScoped +import jakarta.inject.Inject + +/** + * @author Björn Kautler + */ +@ApplicationScoped +class SomeFoo { + @Inject + private Foo foo +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/basic/SomeIFoo.groovy b/spock/src/test/groovy/org/jboss/weld/spock/basic/SomeIFoo.groovy new file mode 100644 index 00000000..b8855cec --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/basic/SomeIFoo.groovy @@ -0,0 +1,30 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.basic + +import jakarta.enterprise.context.ApplicationScoped +import jakarta.inject.Inject + +/** + * @author Björn Kautler + */ +@ApplicationScoped +class SomeIFoo { + @Inject + private IFoo foo +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/basic/unsatisfied/Baz.groovy b/spock/src/test/groovy/org/jboss/weld/spock/basic/unsatisfied/Baz.groovy new file mode 100644 index 00000000..a08e64c0 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/basic/unsatisfied/Baz.groovy @@ -0,0 +1,39 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.basic.unsatisfied + +import jakarta.enterprise.context.ApplicationScoped +import jakarta.inject.Inject +import jakarta.inject.Named + +/** + * @author Björn Kautler + */ +@ApplicationScoped +class Baz { + @Inject + @Named('bar-value') + String bar + + Baz() { + } + + String getBar() { + bar + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/basic/unsatisfied/FooDeps.groovy b/spock/src/test/groovy/org/jboss/weld/spock/basic/unsatisfied/FooDeps.groovy new file mode 100644 index 00000000..8840fb31 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/basic/unsatisfied/FooDeps.groovy @@ -0,0 +1,37 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.basic.unsatisfied + +import jakarta.enterprise.context.ApplicationScoped +import jakarta.inject.Inject + +/** + * @author Björn Kautler + */ +@ApplicationScoped +class FooDeps { + @Inject + Baz baz + + FooDeps() { + } + + String getBar() { + baz.bar + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/basic/unsatisfied/SomeFooDeps.groovy b/spock/src/test/groovy/org/jboss/weld/spock/basic/unsatisfied/SomeFooDeps.groovy new file mode 100644 index 00000000..06f4db47 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/basic/unsatisfied/SomeFooDeps.groovy @@ -0,0 +1,30 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.basic.unsatisfied + +import jakarta.enterprise.context.ApplicationScoped +import jakarta.inject.Inject + +/** + * @author Björn Kautler + */ +@ApplicationScoped +class SomeFooDeps { + @Inject + private FooDeps fooDeps +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/bean/AddBeanTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/bean/AddBeanTest.groovy new file mode 100644 index 00000000..85b2739c --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/bean/AddBeanTest.groovy @@ -0,0 +1,151 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.bean + +import java.util.concurrent.atomic.AtomicInteger + +import jakarta.enterprise.context.ApplicationScoped +import jakarta.enterprise.context.Dependent +import jakarta.enterprise.util.TypeLiteral +import org.jboss.weld.junit.MockBean +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import spock.lang.Execution +import spock.lang.Isolated +import spock.lang.Rollup +import spock.lang.Shared +import spock.lang.Specification + +import static org.spockframework.runtime.model.parallel.ExecutionMode.SAME_THREAD + +/** + * @author Björn Kautler + */ +@EnableWeld +class AddBeanTest extends Specification { + @Shared + def SEQUENCE = new AtomicInteger(0) + + MyService myServiceMock = Mock() + + @WeldSetup + def weld = WeldInitiator + .from(Blue) + .addBeans(MockBean.of(myServiceMock, MyService)) + .addBeans(MockBean.read(BlueToDiscover).scope(Dependent).build()) + .addBeans(createListBean(), createSequenceBean(), createIdSupplierBean()) + .build() + + def createListBean() { + MockBean + .builder() + .types(new TypeLiteral>() {}.type) + .qualifiers(Meaty.Literal.INSTANCE) + .creating(Stub(List) { + get(0) >> '42' + }) + .build() + } + + def createSequenceBean() { + MockBean + .builder() + .types(Integer) + .qualifiers(Meaty.Literal.INSTANCE) + .create { SEQUENCE.incrementAndGet() } + .build() + } + + def createIdSupplierBean() { + MockBean + .builder() + .types(IdSupplier) + .scope(ApplicationScoped) + .create { new IdSupplier(UUID.randomUUID().toString()) } + .build() + } + + interface MyService { + void doBusiness(String name) + } + + static class IdSupplier { + private final String id + + IdSupplier(String id) { + this.id = id + } + + String getId() { + return id + } + } +} + +class ConcurrentAddBeanTest extends AddBeanTest { + def 'Blue should get @Meaty List injected'() { + expect: + weld.select(Blue).get().stringList.get(0) == '42' + } + + @Rollup + @Execution(SAME_THREAD) + def 'each Bean.create() should increment the sequence'() { + expect: + weld.select(Integer, Meaty.Literal.INSTANCE).get() == i + + where: + i << (1..10) + } + + def 'mocking on an injected mock bean should work properly'() { + given: + def myService = weld.select(MyService).get() + + when: + myService.doBusiness('Adalbert') + + then: + 1 * myServiceMock.doBusiness(_) + } + + def 'application scoped beans should work properly'() { + when: + def first = weld.select(IdSupplier).get() + def second = weld.select(IdSupplier).get() + + then: + first.id == second.id + } +} + +@Isolated +class IsolatedAddBeanTest extends AddBeanTest { + def 'the scope of "read" beans should be taken from the manual override'() { + when: + def blue1 = weld.select(BlueToDiscover).get() + def blue2 = weld.select(BlueToDiscover).get() + + then: + blue1.id != null + blue2.id != null + blue1.id != blue2.id + weld.beanManager.getBeans('blue').size() == 1 + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/bean/AddGloballyEnabledAlternativeTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/bean/AddGloballyEnabledAlternativeTest.groovy new file mode 100644 index 00000000..cfd080cd --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/bean/AddGloballyEnabledAlternativeTest.groovy @@ -0,0 +1,88 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.bean + +import jakarta.enterprise.inject.spi.Bean +import jakarta.enterprise.util.TypeLiteral +import org.jboss.weld.junit.MockBean +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import spock.lang.Isolated +import spock.lang.Specification + +/** + * Tests {@link org.jboss.weld.junit.MockBean} adding a bean that is a globally enabled alternative. + * + * @author Björn Kautler + */ +@Isolated +@EnableWeld +class AddGloballyEnabledAlternativeTest extends Specification { + @WeldSetup + def weld = WeldInitiator + .from(Bar) + .addBeans(createFooAlternativeBean(), createListBean()) + .build() + + static Bean createFooAlternativeBean() { + return MockBean + .read(Foo) + .priority(3) + .alternative(true) + .addQualifier(Meaty.Literal.INSTANCE) + .build() + } + + Bean createListBean() { + return MockBean + .builder() + .types(new TypeLiteral>() {}.type) + .globallySelectedAlternative(2) + .creating(Stub(List) { + get(0) >> '42' + }) + .build() + } + + def 'all alternative beans should be added'() { + when: + def bar = weld.select(Bar).get() + + then: + bar.foo != null + bar.someList != null + bar.someList.get(0) == '42' + } + + def 'all alternative beans can be selected'() { + when: + def beans = weld.beanManager.getBeans(Foo, Meaty.Literal.INSTANCE) + + then: + beans.size() == 1 + beans.first().alternative + + when: + beans = weld.beanManager.getBeans(new TypeLiteral>() {}.type) + + then: + beans.size() == 1 + beans.first().alternative + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/bean/AddPassivatingBeanTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/bean/AddPassivatingBeanTest.groovy new file mode 100644 index 00000000..65a52d08 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/bean/AddPassivatingBeanTest.groovy @@ -0,0 +1,56 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.bean + +import jakarta.enterprise.context.SessionScoped +import jakarta.enterprise.inject.spi.Bean +import jakarta.enterprise.util.TypeLiteral +import org.jboss.weld.junit.MockBean +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld +class AddPassivatingBeanTest extends Specification { + @WeldSetup + def weld = WeldInitiator + .from(List) + .addBeans(createListBean()) + .activate(SessionScoped) + .build() + + Bean createListBean() { + return MockBean + .builder() + .types(new TypeLiteral>() {}.type) + .scope(SessionScoped) + .creating(Stub(List) { + get(0) >> '42' + }) + .build() + } + + def 'passivating bean should work properly'() { + expect: + weld.select(new TypeLiteral>() {}).get().get(0) == '42' + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/bean/AlternativeMockBeanTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/bean/AlternativeMockBeanTest.groovy new file mode 100644 index 00000000..bc9e6489 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/bean/AlternativeMockBeanTest.groovy @@ -0,0 +1,67 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.bean + +import jakarta.enterprise.context.Dependent +import org.jboss.weld.junit.MockBean +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld +class AlternativeMockBeanTest extends Specification { + @WeldSetup + def weld = WeldInitiator + .from(SimpleService) + .addBeans(MockBean + .builder() + .types(MyService) + .selectedAlternative() + .beanClass(CoolService) + .create { new CoolService() } + .build()) + .build() + + def 'alternative bean should be selected'() { + expect: + weld.select(MyService).get().doBusiness() == 1000 + } + + interface MyService { + int doBusiness() + } + + @Dependent + static class SimpleService implements MyService { + @Override + int doBusiness() { + return 0 + } + } + + static class CoolService implements MyService { + @Override + int doBusiness() { + return 1000 + } + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/bean/Bar.groovy b/spock/src/test/groovy/org/jboss/weld/spock/bean/Bar.groovy new file mode 100644 index 00000000..1eadf91a --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/bean/Bar.groovy @@ -0,0 +1,42 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.bean + +import jakarta.enterprise.context.ApplicationScoped +import jakarta.inject.Inject + +/** + * @author Björn Kautler + */ +@ApplicationScoped +class Bar { + @Inject + @Meaty + private Foo foo + + @Inject + private List someList + + List getSomeList() { + return someList + } + + Foo getFoo() { + return foo + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/bean/Blue.groovy b/spock/src/test/groovy/org/jboss/weld/spock/bean/Blue.groovy new file mode 100644 index 00000000..7d66678a --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/bean/Blue.groovy @@ -0,0 +1,35 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.bean + +import jakarta.enterprise.context.ApplicationScoped +import jakarta.inject.Inject + +/** + * @author Björn Kautler + */ +@ApplicationScoped +class Blue { + @Inject + @Meaty + private List stringList + + List getStringList() { + return stringList + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/bean/BlueToDiscover.groovy b/spock/src/test/groovy/org/jboss/weld/spock/bean/BlueToDiscover.groovy new file mode 100644 index 00000000..38a29af8 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/bean/BlueToDiscover.groovy @@ -0,0 +1,40 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.bean + +import jakarta.annotation.PostConstruct +import jakarta.enterprise.context.ApplicationScoped +import jakarta.inject.Named + +/** + * @author Björn Kautler + */ +@Named('blue') +@ApplicationScoped +class BlueToDiscover { + private String id + + @PostConstruct + void init() { + this.id = UUID.randomUUID().toString() + } + + String getId() { + return id + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/bean/Foo.groovy b/spock/src/test/groovy/org/jboss/weld/spock/bean/Foo.groovy new file mode 100644 index 00000000..3473d2bc --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/bean/Foo.groovy @@ -0,0 +1,27 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.bean + +/** + * @author Björn Kautler + */ +class Foo { + String ping() { + 'foo' + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/bean/Meaty.groovy b/spock/src/test/groovy/org/jboss/weld/spock/bean/Meaty.groovy new file mode 100644 index 00000000..3c3617c5 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/bean/Meaty.groovy @@ -0,0 +1,47 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.bean + +import java.lang.annotation.Retention +import java.lang.annotation.Target + +import jakarta.enterprise.util.AnnotationLiteral +import jakarta.inject.Qualifier + +import static java.lang.annotation.ElementType.FIELD +import static java.lang.annotation.ElementType.METHOD +import static java.lang.annotation.ElementType.PARAMETER +import static java.lang.annotation.ElementType.TYPE +import static java.lang.annotation.RetentionPolicy.RUNTIME + +/** + * @author Björn Kautler + */ +@Qualifier +@Target([TYPE, METHOD, PARAMETER, FIELD]) +@Retention(RUNTIME) +@interface Meaty { + static class Literal extends AnnotationLiteral implements Meaty { + private static final long serialVersionUID = 1L + + public static final Meaty INSTANCE = new Literal() + + private Literal() { + } + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/bean/MockBeanWithQualifiersTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/bean/MockBeanWithQualifiersTest.groovy new file mode 100644 index 00000000..9481df21 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/bean/MockBeanWithQualifiersTest.groovy @@ -0,0 +1,49 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.bean + +import jakarta.enterprise.inject.Any +import org.jboss.weld.junit.MockBean +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import spock.lang.Specification + +/** + * Tests that {@link MockBean} with custom qualifiers has {@link Any} qualifier automatically added. + * + * @author Björn Kautler + */ +@EnableWeld +class MockBeanWithQualifiersTest extends Specification { + @WeldSetup + def weld = WeldInitiator + .from(AlternativeMockBeanTest.SimpleService) + .addBeans(MockBean + .builder() + .types(String) + .qualifiers(Meaty.Literal.INSTANCE) + .create { 'foo' } + .build()) + .build() + + void 'mock beans with custom qualifiers should have the Any qualifier automatically'() { + expect: + weld.select(String, Any.Literal.INSTANCE).get() == 'foo' + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/bean/TestClassProducerTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/bean/TestClassProducerTest.groovy new file mode 100644 index 00000000..495cce7b --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/bean/TestClassProducerTest.groovy @@ -0,0 +1,50 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.bean + +import jakarta.enterprise.context.ApplicationScoped +import jakarta.enterprise.inject.Produces +import jakarta.enterprise.util.TypeLiteral +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import spock.lang.Specification + +/** + * Note that we add the class to the deployment so it is recognized as a bean and therefore the producer is also discovered. + * + * @author Björn Kautler + */ +@EnableWeld +class TestClassProducerTest extends Specification { + @WeldSetup + def weld = WeldInitiator.from(List, TestClassProducerTest).build() + + def 'bean from producer method should be found'() { + expect: + weld.select(new TypeLiteral>() {}).get().get(0) == '42' + } + + @ApplicationScoped + @Produces + List produceList() { + Stub(List) { + get(0) >> '42' + } + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/bean/extension/AddExtensionAsBeanClassWithFromMethodTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/bean/extension/AddExtensionAsBeanClassWithFromMethodTest.groovy new file mode 100644 index 00000000..c6d685ee --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/bean/extension/AddExtensionAsBeanClassWithFromMethodTest.groovy @@ -0,0 +1,44 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.bean.extension + +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld +class AddExtensionAsBeanClassWithFromMethodTest extends Specification { + @WeldSetup + def weld = WeldInitiator.from(GoodOldBean, MyExtension).build() + + def 'class added with from should be recognized as extension'() { + expect: 'GoodOldBean should be resolvable' + weld.select(GoodOldBean).resolvable + + when: + def extInstance = weld.select(MyExtension) + + then: 'extension should be resolvable and should have observed the other bean' + extInstance.resolvable + extInstance.get().beanObserved() + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/bean/extension/AddExtensionAsBeanClassWithOfMethodTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/bean/extension/AddExtensionAsBeanClassWithOfMethodTest.groovy new file mode 100644 index 00000000..df582bc8 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/bean/extension/AddExtensionAsBeanClassWithOfMethodTest.groovy @@ -0,0 +1,44 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.bean.extension + +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld +class AddExtensionAsBeanClassWithOfMethodTest extends Specification { + @WeldSetup + def weld = WeldInitiator.of(GoodOldBean, MyExtension) + + def 'class added with of should be recognized as extension'() { + expect: 'GoodOldBean should be resolvable' + weld.select(GoodOldBean).resolvable + + when: + def extInstance = weld.select(MyExtension) + + then: 'extension should be resolvable and should have observed the other bean' + extInstance.resolvable + extInstance.get().beanObserved() + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/bean/extension/GoodOldBean.groovy b/spock/src/test/groovy/org/jboss/weld/spock/bean/extension/GoodOldBean.groovy new file mode 100644 index 00000000..65c3ed59 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/bean/extension/GoodOldBean.groovy @@ -0,0 +1,27 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.bean.extension + +import jakarta.enterprise.context.ApplicationScoped + +/** + * @author Björn Kautler + */ +@ApplicationScoped +class GoodOldBean { +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/bean/extension/MyExtension.groovy b/spock/src/test/groovy/org/jboss/weld/spock/bean/extension/MyExtension.groovy new file mode 100644 index 00000000..12aac3a3 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/bean/extension/MyExtension.groovy @@ -0,0 +1,37 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.bean.extension + +import jakarta.enterprise.event.Observes +import jakarta.enterprise.inject.spi.Extension +import jakarta.enterprise.inject.spi.ProcessAnnotatedType + +/** + * @author Björn Kautler + */ +class MyExtension implements Extension { + private boolean beanObserved = false + + void observePAT(@Observes ProcessAnnotatedType event) { + beanObserved = true + } + + boolean beanObserved() { + return beanObserved + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/contexts/ContextsActivatedTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/contexts/ContextsActivatedTest.groovy new file mode 100644 index 00000000..322cbc91 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/contexts/ContextsActivatedTest.groovy @@ -0,0 +1,48 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.contexts + +import jakarta.enterprise.context.RequestScoped +import jakarta.enterprise.context.SessionScoped +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld +class ContextsActivatedTest extends Specification { + @WeldSetup + def weld = WeldInitiator + .from(Foo, Oof, RequestScopedProducer) + .activate(RequestScoped, SessionScoped) + .build() + + @Inject + String producedString + + def 'normal scopes should behave properly'() { + expect: + weld.select(Foo).get().id == weld.select(Foo).get().id + weld.select(Oof).get().id == weld.select(Oof).get().id + producedString == 'foo' + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/contexts/Foo.groovy b/spock/src/test/groovy/org/jboss/weld/spock/contexts/Foo.groovy new file mode 100644 index 00000000..5e4e6bcb --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/contexts/Foo.groovy @@ -0,0 +1,38 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.contexts + +import jakarta.annotation.PostConstruct +import jakarta.enterprise.context.RequestScoped + +/** + * @author Björn Kautler + */ +@RequestScoped +class Foo { + private String id + + @PostConstruct + void init() { + id = UUID.randomUUID().toString() + } + + String getId() { + return id + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/contexts/InvalidScopeTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/contexts/InvalidScopeTest.groovy new file mode 100644 index 00000000..07e5d241 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/contexts/InvalidScopeTest.groovy @@ -0,0 +1,38 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.contexts + +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld +class InvalidScopeTest extends Specification { + def 'activating a non-scope annotation should throw IllegalArgumentException'() { + when: + // the container doesn't really even start here and it's not proper way to start it + // but it's sufficient to check that only scopes can be activated + WeldInitiator.from(Foo).activate(SomeAnnotation) + + then: + thrown(IllegalArgumentException) + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/contexts/Oof.groovy b/spock/src/test/groovy/org/jboss/weld/spock/contexts/Oof.groovy new file mode 100644 index 00000000..5ebaa74f --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/contexts/Oof.groovy @@ -0,0 +1,38 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.contexts + +import jakarta.annotation.PostConstruct +import jakarta.enterprise.context.SessionScoped + +/** + * @author Björn Kautler + */ +@SessionScoped +class Oof implements Serializable { + private String id + + @PostConstruct + void init() { + id = UUID.randomUUID().toString() + } + + String getId() { + return id + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/contexts/RequestScopedProducer.groovy b/spock/src/test/groovy/org/jboss/weld/spock/contexts/RequestScopedProducer.groovy new file mode 100644 index 00000000..b0559f11 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/contexts/RequestScopedProducer.groovy @@ -0,0 +1,34 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.contexts + +import jakarta.enterprise.context.Dependent +import jakarta.enterprise.context.RequestScoped +import jakarta.enterprise.inject.Produces + +/** + * @author Björn Kautler + */ +@RequestScoped +class RequestScopedProducer { + @Produces + @Dependent + String produceDependentString() { + return 'foo' + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/contexts/SomeAnnotation.groovy b/spock/src/test/groovy/org/jboss/weld/spock/contexts/SomeAnnotation.groovy new file mode 100644 index 00000000..aee3d65e --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/contexts/SomeAnnotation.groovy @@ -0,0 +1,29 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.contexts + +import java.lang.annotation.Retention + +import static java.lang.annotation.RetentionPolicy.RUNTIME + +/** + * @author Björn Kautler + */ +@Retention(RUNTIME) +@interface SomeAnnotation { +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/contexts/events/ContextLifecycleEventsObserver.groovy b/spock/src/test/groovy/org/jboss/weld/spock/contexts/events/ContextLifecycleEventsObserver.groovy new file mode 100644 index 00000000..5d2fe3af --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/contexts/events/ContextLifecycleEventsObserver.groovy @@ -0,0 +1,51 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.contexts.events + +import java.util.concurrent.CopyOnWriteArrayList + +import jakarta.enterprise.context.ApplicationScoped +import jakarta.enterprise.context.Destroyed +import jakarta.enterprise.context.Initialized +import jakarta.enterprise.context.RequestScoped +import jakarta.enterprise.context.SessionScoped +import jakarta.enterprise.event.Observes + +/** + * @author Björn Kautler + */ +@ApplicationScoped +class ContextLifecycleEventsObserver { + static final List EVENTS = new CopyOnWriteArrayList<>() + + void onRequestContextInit(@Observes @Initialized(RequestScoped) event) { + EVENTS.add(Initialized.name + RequestScoped.name) + } + + void onRequestContextDestroy(@Observes @Destroyed(RequestScoped) event) { + EVENTS.add(Destroyed.name + RequestScoped.name) + } + + void onSessionContextInit(@Observes @Initialized(SessionScoped) event) { + EVENTS.add(Initialized.name + SessionScoped.name) + } + + void onSessionContextDestroy(@Observes @Destroyed(SessionScoped) event) { + EVENTS.add(Destroyed.name + SessionScoped.name) + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/contexts/events/ContextLifecycleEventsTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/contexts/events/ContextLifecycleEventsTest.groovy new file mode 100644 index 00000000..cc869231 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/contexts/events/ContextLifecycleEventsTest.groovy @@ -0,0 +1,51 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.contexts.events + +import jakarta.enterprise.context.Destroyed +import jakarta.enterprise.context.Initialized +import jakarta.enterprise.context.RequestScoped +import jakarta.enterprise.context.SessionScoped +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld +class ContextLifecycleEventsTest extends Specification { + @WeldSetup + def weld = WeldInitiator + .from(ContextLifecycleEventsObserver) + .activate(RequestScoped, SessionScoped) + .build() + + def 'scope initialization events were fired when booting up container'() { + expect: + ContextLifecycleEventsObserver.EVENTS.contains(Initialized.name + RequestScoped.name) + ContextLifecycleEventsObserver.EVENTS.contains(Initialized.name + SessionScoped.name) + } + + def cleanupSpec() { + // At this time @Destroyed from the previous test method should be fired + assert ContextLifecycleEventsObserver.EVENTS.contains(Destroyed.name + RequestScoped.name) + assert ContextLifecycleEventsObserver.EVENTS.contains(Destroyed.name + SessionScoped.name) + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/enricher/FooWeldSpockEnricher.groovy b/spock/src/test/groovy/org/jboss/weld/spock/enricher/FooWeldSpockEnricher.groovy new file mode 100644 index 00000000..c0d41c2b --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/enricher/FooWeldSpockEnricher.groovy @@ -0,0 +1,37 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.enricher + +import org.jboss.weld.environment.se.Weld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSpockEnricher +import org.jboss.weld.spock.basic.Foo +import org.jboss.weld.spock.enricher.disabled.WeldSpockEnricherDisabledTest +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +class FooWeldSpockEnricher implements WeldSpockEnricher { + @Override + void enrich(Specification testInstance, Weld weld, WeldInitiator.Builder weldInitiatorBuilder) { + if (testInstance?.getClass() in [WeldSpockEnricherTest, WeldSpockEnricherDisabledTest]) { + weld.addBeanClass(Foo) + } + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/enricher/WeldSpockEnricherTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/enricher/WeldSpockEnricherTest.groovy new file mode 100644 index 00000000..85a0d2ba --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/enricher/WeldSpockEnricherTest.groovy @@ -0,0 +1,42 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.enricher + +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.basic.Foo +import spock.lang.ResourceLock +import spock.lang.Specification + +import static org.spockframework.runtime.model.parallel.ResourceAccessMode.READ +import static org.spockframework.runtime.model.parallel.Resources.SYSTEM_PROPERTIES + +/** + * @author Björn Kautler + */ +@EnableWeld +@ResourceLock(value = SYSTEM_PROPERTIES, mode = READ) +class WeldSpockEnricherTest extends Specification { + @Inject + Foo foo + + def 'weld spock enricher should do its work'() { + expect: + foo.bar == 'baz' + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/enricher/disabled/WeldSpockEnricherDisabledTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/enricher/disabled/WeldSpockEnricherDisabledTest.groovy new file mode 100644 index 00000000..6d48fef0 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/enricher/disabled/WeldSpockEnricherDisabledTest.groovy @@ -0,0 +1,51 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.enricher.disabled + +import jakarta.enterprise.inject.Instance +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.basic.Foo +import org.jboss.weld.spock.enricher.FooWeldSpockEnricher +import spock.lang.ResourceLock +import spock.lang.Specification + +import static org.spockframework.runtime.model.parallel.Resources.SYSTEM_PROPERTIES + +/** + * @author Björn Kautler + */ +@EnableWeld +@ResourceLock(SYSTEM_PROPERTIES) +class WeldSpockEnricherDisabledTest extends Specification { + @Inject + Instance foo + + def setupSpec() { + System.setProperty(FooWeldSpockEnricher.name, 'false') + } + + def cleanupSpec() { + System.clearProperty(FooWeldSpockEnricher.name) + } + + void testCustomizer() { + expect: + foo.unsatisfied + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/event/DummyObserver.groovy b/spock/src/test/groovy/org/jboss/weld/spock/event/DummyObserver.groovy new file mode 100644 index 00000000..8f35864b --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/event/DummyObserver.groovy @@ -0,0 +1,36 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.event + +import java.util.concurrent.CopyOnWriteArrayList + +import jakarta.enterprise.context.ApplicationScoped +import jakarta.enterprise.event.Observes +import org.jboss.weld.spock.basic.Foo + +/** + * @author Björn Kautler + */ +@ApplicationScoped +class DummyObserver { + static final List MESSAGES = new CopyOnWriteArrayList<>() + + void observeHelloMessage(@Observes Foo message) { + MESSAGES.add(message) + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/event/FireEventTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/event/FireEventTest.groovy new file mode 100644 index 00000000..7f7ffc3a --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/event/FireEventTest.groovy @@ -0,0 +1,45 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.event + +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import org.jboss.weld.spock.basic.Foo +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld +class FireEventTest extends Specification { + @WeldSetup + def weld = WeldInitiator.of(DummyObserver) + + def 'event should be fired'() { + given: + DummyObserver.MESSAGES.clear() + + when: 'Fire an event' + weld.event().select(Foo).fire(new Foo()) + + then: + DummyObserver.MESSAGES.size() == 1 + DummyObserver.MESSAGES.first().bar == null + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/Bar.groovy b/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/Bar.groovy new file mode 100644 index 00000000..2262327c --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/Bar.groovy @@ -0,0 +1,39 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.explicitInjection + +import jakarta.enterprise.context.ApplicationScoped + +/** + * @author Björn Kautler + */ +@ApplicationScoped +class Bar { + private String someText + + Bar() { + } + + Bar(String someText) { + this.someText = someText + } + + String ping() { + return someText + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/BeanWithQualifier.groovy b/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/BeanWithQualifier.groovy new file mode 100644 index 00000000..341b788e --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/BeanWithQualifier.groovy @@ -0,0 +1,31 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.explicitInjection + +import jakarta.enterprise.context.ApplicationScoped + +/** + * @author Björn Kautler + */ +@ApplicationScoped +@MyQualifier +class BeanWithQualifier { + String ping() { + return BeanWithQualifier.simpleName + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/CustomExtension.groovy b/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/CustomExtension.groovy new file mode 100644 index 00000000..25c5cdb3 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/CustomExtension.groovy @@ -0,0 +1,54 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.explicitInjection + +import java.lang.annotation.Retention +import java.lang.annotation.Target + +import org.spockframework.runtime.extension.ExtensionAnnotation +import org.spockframework.runtime.extension.IAnnotationDrivenExtension +import org.spockframework.runtime.model.FeatureInfo + +import static java.lang.annotation.ElementType.METHOD +import static java.lang.annotation.RetentionPolicy.RUNTIME +import static org.spockframework.runtime.model.MethodInfo.MISSING_ARGUMENT + +/** + * Custom extension just to verify a case where we cannot handle some types. + * + * @author Björn Kautler + */ +class CustomExtension implements IAnnotationDrivenExtension { + @Override + void visitFeatureAnnotation(Custom custom, FeatureInfo feature) { + Class[] parameterTypes = feature.featureMethod.reflection.parameterTypes + feature.featureMethod.addInterceptor { + it.arguments.eachWithIndex { argument, i -> + if ((argument == MISSING_ARGUMENT) && (parameterTypes[i] == Bar)) { + it.arguments[i] = new Bar(CustomExtension.simpleName) + } + } + } + } +} + +@Retention(RUNTIME) +@Target(METHOD) +@ExtensionAnnotation(CustomExtension) +@interface Custom { +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/ExplicitParameterInjectionViaClassAnnotationTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/ExplicitParameterInjectionViaClassAnnotationTest.groovy new file mode 100644 index 00000000..84843ff6 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/ExplicitParameterInjectionViaClassAnnotationTest.groovy @@ -0,0 +1,40 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.explicitInjection + +import jakarta.enterprise.inject.Default +import org.jboss.weld.spock.EnableWeld +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld(explicitParamInjection = true) +class ExplicitParameterInjectionViaClassAnnotationTest extends Specification { + @Custom + void 'parameters with qualifiers should be injected'(@Default Foo foo, Bar bar, @MyQualifier BeanWithQualifier bean) { + expect: 'Bar should be resolved by another extension' + bar.ping() == CustomExtension.simpleName + + and: 'Foo should be resolved as usual' + foo.ping() == Foo.simpleName + + and: 'BeanWithQualifier should be resolved' + bean.ping() == BeanWithQualifier.simpleName + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/ExplicitParameterInjectionViaMethodAnnotationTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/ExplicitParameterInjectionViaMethodAnnotationTest.groovy new file mode 100644 index 00000000..96b246ef --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/ExplicitParameterInjectionViaMethodAnnotationTest.groovy @@ -0,0 +1,40 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.explicitInjection + +import jakarta.enterprise.inject.Default +import org.jboss.weld.spock.EnableWeld +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +class ExplicitParameterInjectionViaMethodAnnotationTest extends Specification { + @EnableWeld(explicitParamInjection = true) + @Custom + void 'parameters with qualifiers should be injected'(@Default Foo foo, Bar bar, @MyQualifier BeanWithQualifier bean) { + expect: 'Bar should be resolved by another extension' + bar.ping() == CustomExtension.simpleName + + and: 'Foo should be resolved as usual' + foo.ping() == Foo.simpleName + + and: 'BeanWithQualifier should be resolved' + bean.ping() == BeanWithQualifier.simpleName + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/Foo.groovy b/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/Foo.groovy new file mode 100644 index 00000000..4ee79a6b --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/Foo.groovy @@ -0,0 +1,30 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.explicitInjection + +import jakarta.enterprise.context.Dependent + +/** + * @author Björn Kautler + */ +@Dependent +class Foo { + String ping() { + return Foo.simpleName + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/MyQualifier.groovy b/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/MyQualifier.groovy new file mode 100644 index 00000000..3c3136b5 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/explicitInjection/MyQualifier.groovy @@ -0,0 +1,38 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.explicitInjection + +import java.lang.annotation.Retention +import java.lang.annotation.Target + +import jakarta.inject.Qualifier + +import static java.lang.annotation.ElementType.FIELD +import static java.lang.annotation.ElementType.METHOD +import static java.lang.annotation.ElementType.PARAMETER +import static java.lang.annotation.ElementType.TYPE +import static java.lang.annotation.RetentionPolicy.RUNTIME + +/** + * @author Björn Kautler + */ +@Qualifier +@Retention(RUNTIME) +@Target([FIELD, METHOD, TYPE, PARAMETER]) +@interface MyQualifier { +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/extensionInjection/BarBean.groovy b/spock/src/test/groovy/org/jboss/weld/spock/extensionInjection/BarBean.groovy new file mode 100644 index 00000000..cc0a5b1b --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/extensionInjection/BarBean.groovy @@ -0,0 +1,31 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.extensionInjection + +import jakarta.enterprise.context.ApplicationScoped + +/** + * @author Björn Kautler + */ +@ApplicationScoped +@MyQualifier +class BarBean { + String ping() { + return BarBean.simpleName + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/extensionInjection/FooBean.groovy b/spock/src/test/groovy/org/jboss/weld/spock/extensionInjection/FooBean.groovy new file mode 100644 index 00000000..38717347 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/extensionInjection/FooBean.groovy @@ -0,0 +1,30 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.extensionInjection + +import jakarta.enterprise.context.Dependent + +/** + * @author Björn Kautler + */ +@Dependent +class FooBean { + String ping() { + return FooBean.simpleName + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/extensionInjection/MyQualifier.groovy b/spock/src/test/groovy/org/jboss/weld/spock/extensionInjection/MyQualifier.groovy new file mode 100644 index 00000000..107fe2e4 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/extensionInjection/MyQualifier.groovy @@ -0,0 +1,37 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.extensionInjection + +import java.lang.annotation.Retention +import java.lang.annotation.Target + +import jakarta.inject.Qualifier + +import static java.lang.annotation.ElementType.FIELD +import static java.lang.annotation.ElementType.PARAMETER +import static java.lang.annotation.ElementType.TYPE +import static java.lang.annotation.RetentionPolicy.RUNTIME + +/** + * @author Björn Kautler + */ +@Qualifier +@Target([FIELD, PARAMETER, TYPE]) +@Retention(RUNTIME) +@interface MyQualifier { +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/extensionInjection/SomeBean.groovy b/spock/src/test/groovy/org/jboss/weld/spock/extensionInjection/SomeBean.groovy new file mode 100644 index 00000000..adca5105 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/extensionInjection/SomeBean.groovy @@ -0,0 +1,30 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.extensionInjection + +import jakarta.enterprise.context.ApplicationScoped + +/** + * @author Björn Kautler + */ +@ApplicationScoped +class SomeBean { + String ping() { + return SomeBean.simpleName + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/extensionInjection/SpockInjectionTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/extensionInjection/SpockInjectionTest.groovy new file mode 100644 index 00000000..71a3a499 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/extensionInjection/SpockInjectionTest.groovy @@ -0,0 +1,125 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.extensionInjection + +import jakarta.inject.Inject +import org.jboss.weld.spock.EnableWeld +import spock.lang.Execution +import spock.lang.Rollup +import spock.lang.Shared +import spock.lang.Specification + +import static org.jboss.weld.spock.EnableWeld.Scope.FEATURE +import static org.jboss.weld.spock.EnableWeld.Scope.SPECIFICATION +import static org.spockframework.runtime.model.parallel.ExecutionMode.SAME_THREAD + +/** + * Basic test for Spock injection into parameter/field handled by Weld + * + * @author Björn Kautler + */ +@EnableWeld +@Execution(SAME_THREAD) +class SpockInjectionTest extends Specification { + @Inject + SomeBean bean + + @Inject + @Shared + SomeBean sharedBean + + def setupBean + + def setup(SomeBean setupBean) { + this.setupBean = setupBean + } + + def 'field should be injected'() { + expect: + bean != null + bean.ping() + } + + def 'shared field should be injected with scope ITERATION'() { + expect: + sharedBean != null + sharedBean.ping() + } + + @EnableWeld(scope = FEATURE) + def 'shared field should be injected with scope FEATURE'() { + expect: + sharedBean != null + sharedBean.ping() + } + + @Rollup + @EnableWeld(scope = FEATURE) + def 'shared field should be injected with scope FEATURE for data-driven feature'() { + expect: + sharedBean != null + sharedBean.ping() + + where: + i = 1 + } + + def 'parameter should be injected'(FooBean foo) { + expect: + foo != null + foo.ping() + } + + def 'parameter with qualifier should be injected'(@MyQualifier BarBean bar) { + expect: + bar != null + bar.ping() + } + + def 'parameter should be injected into setup method'() { + expect: + setupBean != null + setupBean.ping() + } +} + +@EnableWeld(scope = SPECIFICATION) +class SpecificationSpockInjectionTest extends Specification { + @Inject + @Shared + SomeBean sharedBean + + @Shared + def setupSpecBean + + def setupSpec(SomeBean setupSpecBean) { + this.setupSpecBean = setupSpecBean + } + + def 'shared field should be injected with scope SPECIFICATION'() { + expect: + sharedBean != null + sharedBean.ping() + } + + def 'parameter should be injected into setupSpec method with scope SPECIFICATION'() { + expect: + setupSpecBean != null + setupSpecBean.ping() + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/initiator/bean/Foo.groovy b/spock/src/test/groovy/org/jboss/weld/spock/initiator/bean/Foo.groovy new file mode 100644 index 00000000..6e02e214 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/initiator/bean/Foo.groovy @@ -0,0 +1,24 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.initiator.bean + +/** + * @author Björn Kautler + */ +class Foo { +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/initiator/discovery/PrivateWeldInitiatorTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/initiator/discovery/PrivateWeldInitiatorTest.groovy new file mode 100644 index 00000000..8dca2d2e --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/initiator/discovery/PrivateWeldInitiatorTest.groovy @@ -0,0 +1,41 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.initiator.discovery + +import org.jboss.weld.environment.se.Weld +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import org.jboss.weld.spock.initiator.bean.Foo +import spock.lang.Specification + +/** + * Tests a case where WeldInitiator is a private field in a test class + * + * @author Björn Kautler + */ +@EnableWeld +class PrivateWeldInitiatorTest extends Specification { + @WeldSetup + private weld = WeldInitiator.of(new Weld().addBeanClass(Foo)) + + def 'Weld can be initialized from an initiator in a private field'() { + expect: + weld.select(Foo).get() != null + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/initiator/discovery/ProtectedWeldInitiatorInSuperclassTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/initiator/discovery/ProtectedWeldInitiatorInSuperclassTest.groovy new file mode 100644 index 00000000..84ed02a8 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/initiator/discovery/ProtectedWeldInitiatorInSuperclassTest.groovy @@ -0,0 +1,34 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.initiator.discovery + +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.initiator.bean.Foo + +/** + * Tests a case where WeldInitiator comes from a protected field in a superclass + * + * @author Björn Kautler + */ +@EnableWeld +class ProtectedWeldInitiatorInSuperclassTest extends SuperclassWithProtectedWeldInitiator { + def 'Weld can be initialized from an initiator in a protected field of a super spec'() { + expect: + weld.select(Foo).get() != null + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/initiator/discovery/SuperclassWithProtectedWeldInitiator.groovy b/spock/src/test/groovy/org/jboss/weld/spock/initiator/discovery/SuperclassWithProtectedWeldInitiator.groovy new file mode 100644 index 00000000..d03d6f96 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/initiator/discovery/SuperclassWithProtectedWeldInitiator.groovy @@ -0,0 +1,32 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.initiator.discovery + +import org.jboss.weld.environment.se.Weld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import org.jboss.weld.spock.initiator.bean.Foo +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +class SuperclassWithProtectedWeldInitiator extends Specification { + @WeldSetup + protected weld = WeldInitiator.of(new Weld().addBeanClass(Foo)) +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/initiator/discovery/SuperclassWithWeldInitiator.groovy b/spock/src/test/groovy/org/jboss/weld/spock/initiator/discovery/SuperclassWithWeldInitiator.groovy new file mode 100644 index 00000000..f9277b0b --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/initiator/discovery/SuperclassWithWeldInitiator.groovy @@ -0,0 +1,34 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.initiator.discovery + +import org.jboss.weld.environment.se.Weld +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import org.jboss.weld.spock.initiator.bean.Foo +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld +abstract class SuperclassWithWeldInitiator extends Specification { + @WeldSetup + def weld = WeldInitiator.of(new Weld().addBeanClass(Foo)) +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/initiator/discovery/SuperclassWithWeldInitiatorTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/initiator/discovery/SuperclassWithWeldInitiatorTest.groovy new file mode 100644 index 00000000..8af59e23 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/initiator/discovery/SuperclassWithWeldInitiatorTest.groovy @@ -0,0 +1,30 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.initiator.discovery + +import org.jboss.weld.spock.initiator.bean.Foo + +/** + * @author Björn Kautler + */ +class SuperclassWithWeldInitiatorTest extends SuperclassWithWeldInitiator { + def 'Weld can be initialized from an initiator in a super spec'() { + expect: + weld.select(Foo).get() != null + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/interceptor/MockInterceptorTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/interceptor/MockInterceptorTest.groovy new file mode 100644 index 00000000..fc70afa2 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/interceptor/MockInterceptorTest.groovy @@ -0,0 +1,121 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.interceptor + +import java.lang.annotation.Documented +import java.lang.annotation.Retention +import java.lang.annotation.Target + +import jakarta.enterprise.util.AnnotationLiteral +import jakarta.interceptor.InterceptorBinding +import org.jboss.weld.junit.MockInterceptor +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import spock.lang.Specification + +import static jakarta.enterprise.inject.spi.InterceptionType.AROUND_INVOKE +import static java.lang.annotation.ElementType.METHOD +import static java.lang.annotation.ElementType.TYPE +import static java.lang.annotation.RetentionPolicy.RUNTIME + +/** + * @author Björn Kautler + */ +@EnableWeld +class MockInterceptorTest extends Specification { + def aroundInvokes = [] + + def postConstructs = [] + + @WeldSetup + def weld = WeldInitiator + .from(Foo) + .addBeans( + MockInterceptor + .withBindings(BarBinding.Literal.INSTANCE) + .aroundInvoke { ctx, b -> + aroundInvokes.add(b.beanClass.name) + ctx.proceed() + }, + // This interceptor is disabled + MockInterceptor + .withBindings(BarBinding.Literal.INSTANCE) + .beanClass(String) + .aroundInvoke { ctx, b -> + false + }, + MockInterceptor + .withBindings(FooBinding.Literal.INSTANCE) + .postConstruct { ctx, b -> + postConstructs.add(b.beanClass.name) + }) + .build() + + def 'interception should work properly'() { + expect: + aroundInvokes.empty + postConstructs.empty + + when: + def pong = weld.select(Foo).get().ping() + + then: + pong + verifyAll { + aroundInvokes == [Foo.name] + postConstructs == [Foo.name] + } + } + + def 'disabled interceptor should not be resolved'() { + when: + def interceptors = weld.beanManager.resolveInterceptors(AROUND_INVOKE, BarBinding.Literal.INSTANCE) + + then: + interceptors*.beanClass == [MockInterceptor] + } + + @FooBinding + static class Foo { + @BarBinding + boolean ping() { + return true + } + } + + @Target(TYPE) + @Retention(RUNTIME) + @Documented + @InterceptorBinding + static @interface FooBinding { + static final class Literal extends AnnotationLiteral implements FooBinding { + public static final Literal INSTANCE = new Literal() + } + } + + @Target(METHOD) + @Retention(RUNTIME) + @Documented + @InterceptorBinding + static @interface BarBinding { + static final class Literal extends AnnotationLiteral implements BarBinding { + public static final Literal INSTANCE = new Literal() + } + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/ofpackage/Alpha.groovy b/spock/src/test/groovy/org/jboss/weld/spock/ofpackage/Alpha.groovy new file mode 100644 index 00000000..9b4bcf4c --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/ofpackage/Alpha.groovy @@ -0,0 +1,38 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.ofpackage + +import jakarta.annotation.PostConstruct +import jakarta.enterprise.context.Dependent + +/** + * @author Björn Kautler + */ +@Dependent +class Alpha { + private String value + + @PostConstruct + void init() { + value = this.getClass().simpleName.toLowerCase() + } + + String getValue() { + return value + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/ofpackage/Bravo.groovy b/spock/src/test/groovy/org/jboss/weld/spock/ofpackage/Bravo.groovy new file mode 100644 index 00000000..a2885d32 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/ofpackage/Bravo.groovy @@ -0,0 +1,38 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.ofpackage + +import jakarta.annotation.PostConstruct +import jakarta.enterprise.context.Dependent + +/** + * @author Björn Kautler + */ +@Dependent +class Bravo { + private String value + + @PostConstruct + void init() { + value = this.getClass().simpleName.toLowerCase() + } + + String getValue() { + return value + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/ofpackage/OfPackageTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/ofpackage/OfPackageTest.groovy new file mode 100644 index 00000000..2318eec0 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/ofpackage/OfPackageTest.groovy @@ -0,0 +1,40 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.ofpackage + +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import org.jboss.weld.spock.basic.Foo +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld +class OfPackageTest extends Specification { + @WeldSetup + def weld = WeldInitiator.ofTestPackage() + + def 'ofTestPackage should add beans in the package of the test class'() { + expect: + weld.select(Alpha).get().value == 'alpha' + weld.select(Bravo).resolvable + !weld.select(Foo).resolvable + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/resources/DummySessionBean.groovy b/spock/src/test/groovy/org/jboss/weld/spock/resources/DummySessionBean.groovy new file mode 100644 index 00000000..4318a6f5 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/resources/DummySessionBean.groovy @@ -0,0 +1,29 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.resources + +/** + * @author Björn Kautler + */ +class DummySessionBean { + final String id + + DummySessionBean(String id) { + this.id = id + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/resources/FooEjbs.groovy b/spock/src/test/groovy/org/jboss/weld/spock/resources/FooEjbs.groovy new file mode 100644 index 00000000..54ff7f1b --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/resources/FooEjbs.groovy @@ -0,0 +1,30 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.resources + +import jakarta.ejb.EJB +import jakarta.enterprise.context.Dependent + +/** + * @author Björn Kautler + */ +@Dependent +class FooEjbs { + @EJB + DummySessionBean dummySessionBean +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/resources/FooJpa.groovy b/spock/src/test/groovy/org/jboss/weld/spock/resources/FooJpa.groovy new file mode 100644 index 00000000..4225a462 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/resources/FooJpa.groovy @@ -0,0 +1,36 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.resources + +import jakarta.enterprise.context.Dependent +import jakarta.persistence.EntityManager +import jakarta.persistence.EntityManagerFactory +import jakarta.persistence.PersistenceContext +import jakarta.persistence.PersistenceUnit + +/** + * @author Björn Kautler + */ +@Dependent +class FooJpa { + @PersistenceContext + EntityManager entityManager + + @PersistenceUnit + EntityManagerFactory entityManagerFactory +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/resources/FooResources.groovy b/spock/src/test/groovy/org/jboss/weld/spock/resources/FooResources.groovy new file mode 100644 index 00000000..6d1c4e0d --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/resources/FooResources.groovy @@ -0,0 +1,37 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.resources + +import jakarta.annotation.Resource +import jakarta.enterprise.context.Dependent + +/** + * @author Björn Kautler + */ +@Dependent +class FooResources { + @Resource(lookup = 'bar') + String bar + + String baz + + @Resource(name = 'baz') + void setBaz(String baz) { + this.baz = baz + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/resources/InjectResourcesTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/resources/InjectResourcesTest.groovy new file mode 100644 index 00000000..8421a9e1 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/resources/InjectResourcesTest.groovy @@ -0,0 +1,69 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.resources + +import jakarta.persistence.EntityManager +import jakarta.persistence.EntityManagerFactory +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import spock.lang.Specification + +/** + * @author Björn Kautler + */ +@EnableWeld +class InjectResourcesTest extends Specification { + @WeldSetup + def weld = WeldInitiator + .fromTestPackage() + .bindResource('bar', 'hello1') + .bindResource('java:comp/env/baz', 'hello2') + .setEjbFactory { new DummySessionBean('ping') } + .setPersistenceUnitFactory { Mock(EntityManagerFactory) } + .setPersistenceContextFactory { Mock(EntityManager) } + .build() + + def 'resource injection should work properly'() { + when: + def foo = weld.select(FooResources).get() + + then: + foo.bar == 'hello1' + foo.baz == 'hello2' + } + + def 'EJB injection should work properly'() { + when: + def foo = weld.select(FooEjbs).get() + + then: + foo.dummySessionBean.id == 'ping' + } + + def 'JPA injection should work properly'() { + when: + def foo = weld.select(FooJpa).get() + + then: + foo.entityManagerFactory != null + !foo.entityManagerFactory.open + foo.entityManager != null + !foo.entityManager.open + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/scope/PlainBean.groovy b/spock/src/test/groovy/org/jboss/weld/spock/scope/PlainBean.groovy new file mode 100644 index 00000000..444e880f --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/scope/PlainBean.groovy @@ -0,0 +1,27 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.scope + +import jakarta.enterprise.context.ApplicationScoped + +/** + * @author Björn Kautler + */ +@ApplicationScoped +class PlainBean { +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/scope/WeldScopeTest.groovy b/spock/src/test/groovy/org/jboss/weld/spock/scope/WeldScopeTest.groovy new file mode 100644 index 00000000..331536b9 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/scope/WeldScopeTest.groovy @@ -0,0 +1,94 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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.spock.scope + +import org.jboss.weld.environment.se.Weld +import org.jboss.weld.environment.se.WeldContainer +import org.jboss.weld.spock.EnableWeld +import org.jboss.weld.spock.WeldInitiator +import org.jboss.weld.spock.WeldSetup +import spock.lang.Isolated +import spock.lang.Rollup +import spock.lang.Shared +import spock.lang.Specification + +import static org.jboss.weld.spock.EnableWeld.Scope.FEATURE +import static org.jboss.weld.spock.EnableWeld.Scope.SPECIFICATION + +/** + * @author Björn Kautler + */ +class WeldScopeTest extends Specification { + @WeldSetup + def initiator = WeldInitiator.of(new Weld(String.valueOf(System.nanoTime())) + .disableDiscovery().addBeanClass(PlainBean)) + + @Shared + def containerId +} + +@Isolated +@EnableWeld(scope = SPECIFICATION) +class SpecificationWeldScopeTest extends WeldScopeTest { + @Rollup + def 'all iterations should use the same container with scope SPECIFICATION'() { + given: + if (containerId == null) { + containerId = WeldContainer.current().id + } + + expect: + containerId == WeldContainer.current().id + + where: + i << (1..2) + } +} + +@Isolated +class OthersWeldScopeTest extends WeldScopeTest { + @Rollup + @EnableWeld(scope = FEATURE) + def 'all iterations should use the same container with scope FEATURE'() { + given: + if (containerId == null) { + containerId = WeldContainer.current().id + } + + expect: + containerId == WeldContainer.current().id + + where: + i << (1..2) + } + + @Rollup + @EnableWeld + def 'all iterations should use different containers with scope ITERATION'() { + given: + if (containerId == null) { + containerId = WeldContainer.current().id + } + + expect: + containerId != WeldContainer.current().id + + where: + i << (1..2) + } +} diff --git a/spock/src/test/groovy/org/jboss/weld/spock/util/EmbeddedSpecRunnerWrapper.groovy b/spock/src/test/groovy/org/jboss/weld/spock/util/EmbeddedSpecRunnerWrapper.groovy new file mode 100644 index 00000000..1131c7c5 --- /dev/null +++ b/spock/src/test/groovy/org/jboss/weld/spock/util/EmbeddedSpecRunnerWrapper.groovy @@ -0,0 +1,30 @@ +package org.jboss.weld.spock.util + +import org.junit.platform.engine.DiscoverySelector +import org.junit.platform.testkit.engine.EngineTestKit +import spock.util.EmbeddedSpecRunner + +/** + * Work-around for a strange Groovy behavior. + * + *

The embedded spec runner is used to test the exception if there is automagic mode combined with + * {@code @WeldSetup}. But for whatever reason, without this wrapper that just has a plain copy of the private + * {@code doRunRequest} method in the parent class, we get a {@code NoMethodFoundException}. + * + *

Until someone finds out where this problem comes from, this ugly hack at least works in the meantime. + * + * @author Björn Kautler + */ +class EmbeddedSpecRunnerWrapper extends EmbeddedSpecRunner { + SummarizedEngineExecutionResults doRunRequest(List selectors) { + def executionResults = EngineTestKit + .engine("spock") + .selectors(*selectors) + .execute() + def first = executionResults.allEvents().executions().failed().stream().findFirst() + if (first.present) { + throw first.get().terminationInfo.executionResult.throwable.get() + } + return new SummarizedEngineExecutionResults(executionResults) + } +} diff --git a/spock/src/test/resources/META-INF/services/org.jboss.weld.spock.WeldSpockEnricher b/spock/src/test/resources/META-INF/services/org.jboss.weld.spock.WeldSpockEnricher new file mode 100644 index 00000000..0fdaa8fa --- /dev/null +++ b/spock/src/test/resources/META-INF/services/org.jboss.weld.spock.WeldSpockEnricher @@ -0,0 +1 @@ +org.jboss.weld.spock.enricher.FooWeldSpockEnricher diff --git a/spock/src/test/resources/SpockConfig.groovy b/spock/src/test/resources/SpockConfig.groovy new file mode 100644 index 00000000..202ff490 --- /dev/null +++ b/spock/src/test/resources/SpockConfig.groovy @@ -0,0 +1,22 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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. + */ + +runner { + parallel { + enabled true + } +} diff --git a/spock/src/test/resources/log4j2-test.xml b/spock/src/test/resources/log4j2-test.xml new file mode 100644 index 00000000..a982c6f0 --- /dev/null +++ b/spock/src/test/resources/log4j2-test.xml @@ -0,0 +1,16 @@ + + + + + + <%-35.35t> <%x> <%X> <%50.50c> %m}{TRACE = magenta}%n]]> + + + + + + + + + +