blob: 0e73a3b2f122143e65f646d2b7daf07b3fc86c66 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// 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.apache.cloudstack.test.utils;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import com.cloud.utils.component.ComponentContext;
import com.cloud.utils.component.ComponentInstantiationPostProcessor;
import com.cloud.utils.component.ComponentMethodInterceptor;
import com.cloud.utils.db.TransactionContextBuilder;
import com.cloud.utils.exception.CloudRuntimeException;
public class SpringUtils {
/**
* This method allows you to use @ComponentScan for your unit testing but
* it limits the scope of the classes found to the class specified in
* the @ComponentScan annotation.
*
* Without using this method, the default behavior of @ComponentScan is
* to actually scan in the package of the class specified rather than
* only the class. This can cause extra classes to be loaded which causes
* the classes these extra classes depend on to be loaded. The end effect
* is often most of the project gets loaded.
*
* In order to use this method properly, you must do the following: <li>
* - Specify @ComponentScan with basePackageClasses, includeFilters, and
* useDefaultFilters=true. See the following example.
*
* <pre>
* @ComponentScan(basePackageClasses={AffinityGroupServiceImpl.class, EventUtils.class},
* includeFilters={@Filter(value=TestConfiguration.Library.class, type=FilterType.CUSTOM)},
* useDefaultFilters=false)
* </pre>
*
* - Create a Library class and use that to call this method. See the
* following example. The Library class you define here is the Library
* class being added in the filter above.
*
* <pre>
* public static class Library implements TypeFilter {
* @Override
* public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException {
* ComponentScan cs = TestConfiguration.class.getAnnotation(ComponentScan.class);
* return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs);
* }
* }
* </pre>
*
* @param clazzName name of the class that should be included in the Spring components
* @param cs ComponentScan annotation that was declared on the configuration
*
* @return
*/
public static boolean includedInBasePackageClasses(String clazzName, ComponentScan cs) {
Class<?> clazzToCheck;
try {
clazzToCheck = Class.forName(clazzName);
} catch (ClassNotFoundException e) {
throw new CloudRuntimeException("Unable to find " + clazzName);
}
Class<?>[] clazzes = cs.basePackageClasses();
for (Class<?> clazz : clazzes) {
if (clazzToCheck.isAssignableFrom(clazz)) {
return true;
}
}
return false;
}
public static class CloudStackTestConfiguration {
@Bean
public ComponentContext componentContext() {
return new ComponentContext();
}
@Bean
public TransactionContextBuilder transactionContextBuilder() {
return new TransactionContextBuilder();
}
@Bean
public ComponentInstantiationPostProcessor instantiatePostProcessor() {
ComponentInstantiationPostProcessor processor = new ComponentInstantiationPostProcessor();
List<ComponentMethodInterceptor> interceptors = new ArrayList<ComponentMethodInterceptor>();
interceptors.add(new TransactionContextBuilder());
processor.setInterceptors(interceptors);
return processor;
}
}
}