GriffonUnitRule.java
001 /*
002  * SPDX-License-Identifier: Apache-2.0
003  *
004  * Copyright 2008-2017 the original author or authors.
005  *
006  * Licensed under the Apache License, Version 2.0 (the "License");
007  * you may not use this file except in compliance with the License.
008  * You may obtain a copy of the License at
009  *
010  *     http://www.apache.org/licenses/LICENSE-2.0
011  *
012  * Unless required by applicable law or agreed to in writing, software
013  * distributed under the License is distributed on an "AS IS" BASIS,
014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015  * See the License for the specific language governing permissions and
016  * limitations under the License.
017  */
018 package griffon.core.test;
019 
020 import griffon.core.ApplicationBootstrapper;
021 import griffon.core.GriffonApplication;
022 import griffon.core.artifact.GriffonArtifact;
023 import griffon.core.artifact.GriffonClass;
024 import griffon.core.env.Environment;
025 import org.codehaus.griffon.runtime.core.DefaultGriffonApplication;
026 import org.codehaus.griffon.runtime.core.TestApplicationBootstrapper;
027 import org.junit.rules.MethodRule;
028 import org.junit.runners.model.FrameworkMethod;
029 import org.junit.runners.model.Statement;
030 
031 import javax.annotation.Nonnull;
032 import java.lang.reflect.Constructor;
033 import java.lang.reflect.Field;
034 import java.util.Arrays;
035 
036 import static java.util.Objects.requireNonNull;
037 
038 /**
039  @author Andres Almiray
040  @since 2.0.0
041  */
042 public class GriffonUnitRule implements MethodRule {
043     private String[] startupArgs;
044     private Class<? extends GriffonApplication> applicationClass;
045     private Class<? extends ApplicationBootstrapper> applicationBootstrapper;
046 
047     public GriffonUnitRule() {
048         this(DefaultGriffonApplication.EMPTY_ARGS, DefaultGriffonApplication.class, TestApplicationBootstrapper.class);
049     }
050 
051     public GriffonUnitRule(@Nonnull Class<? extends GriffonApplication> applicationClass) {
052         this(DefaultGriffonApplication.EMPTY_ARGS, applicationClass, TestApplicationBootstrapper.class);
053     }
054 
055     public GriffonUnitRule(@Nonnull Class<? extends GriffonApplication> applicationClass, @Nonnull Class<? extends ApplicationBootstrapper> applicationBootstrapper) {
056         this(DefaultGriffonApplication.EMPTY_ARGS, applicationClass, applicationBootstrapper);
057     }
058 
059     public GriffonUnitRule(@Nonnull String[] startupArgs) {
060         this(startupArgs, DefaultGriffonApplication.class, TestApplicationBootstrapper.class);
061     }
062 
063     public GriffonUnitRule(@Nonnull String[] startupArgs, @Nonnull Class<? extends GriffonApplication> applicationClass) {
064         this(startupArgs, applicationClass, TestApplicationBootstrapper.class);
065     }
066 
067     public GriffonUnitRule(@Nonnull String[] startupArgs, @Nonnull Class<? extends GriffonApplication> applicationClass, @Nonnull Class<? extends ApplicationBootstrapper> applicationBootstrapper) {
068         requireNonNull(startupArgs, "Argument 'startupArgs' must not be null");
069         this.startupArgs = Arrays.copyOf(startupArgs, startupArgs.length);
070         this.applicationClass = requireNonNull(applicationClass, "Argument 'applicationClass' must not be null");
071         this.applicationBootstrapper = requireNonNull(applicationBootstrapper, "Argument 'applicationBootstrapper' must not be null");
072         if (!Environment.isSystemSet()) {
073             System.setProperty(Environment.KEY, Environment.TEST.getName());
074         }
075     }
076 
077     @Override
078     public Statement apply(final Statement base, final FrameworkMethod method, final Object target) {
079         return new Statement() {
080             @Override
081             public void evaluate() throws Throwable {
082                 GriffonApplication application = instantiateApplication();
083                 ApplicationBootstrapper bootstrapper = instantiateApplicationBootstrapper(application, target);
084 
085                 bootstrapper.bootstrap();
086                 application.initialize();
087                 application.getInjector().injectMembers(target);
088                 handleTestForAnnotation(application, target);
089 
090                 before(application, target);
091                 try {
092                     base.evaluate();
093                 finally {
094                     after(application, target);
095                 }
096             }
097         };
098     }
099 
100     protected void before(@Nonnull GriffonApplication application, @Nonnull Object targetthrows Throwable {
101 
102     }
103 
104     protected void after(@Nonnull GriffonApplication application, @Nonnull Object target) {
105         application.shutdown();
106     }
107 
108     @Nonnull
109     private GriffonApplication instantiateApplication() throws Exception {
110         String[] array = new String[0];
111         Constructor<? extends GriffonApplication> ctor = applicationClass.getDeclaredConstructor(array.getClass());
112         return ctor.newInstance(new Object[]{startupArgs});
113     }
114 
115     @Nonnull
116     private ApplicationBootstrapper instantiateApplicationBootstrapper(@Nonnull GriffonApplication application, @Nonnull Object testCasethrows Exception {
117         Constructor<? extends ApplicationBootstrapper> constructor = applicationBootstrapper.getDeclaredConstructor(GriffonApplication.class);
118         ApplicationBootstrapper bootstrapper = constructor.newInstance(application);
119         if (bootstrapper instanceof TestCaseAware) {
120             ((TestCaseAwarebootstrapper).setTestCase(testCase);
121         }
122         return bootstrapper;
123     }
124 
125     private void handleTestForAnnotation(@Nonnull GriffonApplication application, @Nonnull Object targetthrows Exception {
126         TestFor testFor = target.getClass().getAnnotation(TestFor.class);
127         if (testFor != null) {
128             Class<? extends GriffonArtifact> artifactClass = testFor.value();
129             GriffonArtifact artifact = application.getArtifactManager().newInstance(artifactClass);
130             GriffonClass griffonClass = artifact.getGriffonClass();
131             Field artifactField = target.getClass().getDeclaredField(griffonClass.getArtifactType());
132             artifactField.setAccessible(true);
133             artifactField.set(target, artifact);
134         }
135     }
136 }