1

単体テストでは、通常、すべての依存関係を EasyMocks として構成します...そしてそれらを構成します...Spring コンテキスト xml ファイルで、これらの依存関係を次のように追加する必要があります-

<bean id="myService" class="mypackage.EasyMockNiceCreator">
        <property name="iface"
                  value="myservicePackage.MyService"/>
</bean>

ここで、EasyMockNiceCreator は、getObject() メソッドで EasyMock.createNiceMock() を作成する Spring FactoryBean の実装です。

明示的に定義された自動配線された依存関係、フォールバックが見つからない場合、Spring がこの構成を使用するように、これをデフォルト構成にするにはどうすればよいですか。

4

1 に答える 1

1

このコードが役立つと思います-

自動 Bean クリエーター

import com.google.common.collect.Iterables;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

public class AutoBeanDeclarer implements BeanDefinitionRegistryPostProcessor {

    private Collection<String> mockedDefinitions;

    public AutoBeanDeclarer() {
        mockedDefinitions = new ArrayList<String>();
    }

    private Iterable<Field> findAllAutoWired(Class targetBean) {
        List<Field> declaredFields = Arrays.asList(targetBean.getDeclaredFields());
        return Iterables.filter(declaredFields, new Predicate<Field>() {
            @Override
            public boolean apply(Field input) {
                return input.isAnnotationPresent(Autowired.class);
            }
        });
    }

    private void registerOn(final BeanDefinitionRegistry registry,final String beanName, final Class type){
        RootBeanDefinition definition = new RootBeanDefinition(MocksFactory.class);

        MutablePropertyValues values = new MutablePropertyValues();
        values.addPropertyValue(new PropertyValue("type", type));
        definition.setPropertyValues(values);

        registry.registerBeanDefinition(beanName, definition);
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        for(String beanName: registry.getBeanDefinitionNames()) {
            BeanDefinition beanDefinition = registry.getBeanDefinition(beanName);
            String beanClassName = beanDefinition.getBeanClassName();
            try {
                Class beanClass = Class.forName(beanClassName);
                for (final Field field : findAllAutoWired(beanClass)) {
                    String fieldName = field.getName();
                    boolean invalidType = field.getType().isArray() || field.getType().isPrimitive();
                    if( invalidType ) {
                        continue;
                    }
                    if( !registry.isBeanNameInUse(fieldName) ) {
                        registerOn(registry, fieldName, field.getType());
                        mockedDefinitions.add(fieldName);
                        // Now field will be available for autowiring.
                    }
                }
            } catch (ClassNotFoundException ex) {
                Logger.getLogger(AutoBeanDeclarer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        for(String beanName: mockedDefinitions) {
            if( !beanFactory.containsBean(beanName) ) {
                Logger.getLogger(AutoBeanDeclarer.class.getName()).log(Level.SEVERE, "Missing definition %s", beanName);
            }
        }
    }
}

モックファクトリークラス

import org.mockito.Mockito;
import org.springframework.beans.factory.FactoryBean;

public class MocksFactory implements FactoryBean {

    private Class type;// the created object type

    public void setType(final Class type) {
        this.type = type;
    }

    @Override
    public Object getObject() throws Exception {
        return Mockito.mock(type);
    }

    @Override
    public Class getObjectType() {
        return type;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

Context.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <bean id="autoConfigurer" class="....AutoBeanFinder"></bean>

    <bean id="targetClass" class="....Target"></bean>

</beans>

Target クラスで自動配線されたすべてのサービスがモックされます。

于 2013-04-18T10:31:10.207 に答える