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 target) throws 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 testCase) throws Exception {
117 Constructor<? extends ApplicationBootstrapper> constructor = applicationBootstrapper.getDeclaredConstructor(GriffonApplication.class);
118 ApplicationBootstrapper bootstrapper = constructor.newInstance(application);
119 if (bootstrapper instanceof TestCaseAware) {
120 ((TestCaseAware) bootstrapper).setTestCase(testCase);
121 }
122 return bootstrapper;
123 }
124
125 private void handleTestForAnnotation(@Nonnull GriffonApplication application, @Nonnull Object target) throws 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 }
|