【问题标题】:Mocking Spring beans嘲讽春豆
【发布时间】:2011-08-07 23:08:31
【问题描述】:

我想继续this 问题。

foobar 这些答案正是我所需要的。

但是对于bar 示例,spring 不会推断从通用 mock() 方法返回的 bean 的类型。但实际上它与 MockFactoryBean 案例中的情况完全相同,这是有效的。

class MockFactoryBean<T> implements FactoryBean<T> {

    private Class<T> type;

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

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

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

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

<bean id="mockFactory" name="someType" class="com.example.MocksFactory" >
    <property name="type" value="com.example.SomeType" />
</bean>

但是使用 org.mockito.Mockitomock() 工厂方法不起作用

<bean id="dao" class="org.mockito.Mockito" factory-method="mock"> 
    <constructor-arg value="com.example.SomeType" /> 
</bean> 

并且在自动装配时得到 No matching bean of type [ com.example.SomeType ] ...。

@自动连线 public SomeType someType;

这是为什么呢?

使用 MockFactoryBean 的方式非常不方便,因为如果你必须模拟许多 bean,你最终会变成这样:

<bean id="mockFactory1" name="metadataExtractor" class="tests.base.MocksFactory" >
    <property name="type" value="processing.MetadataExtractor" />
</bean>
<bean id="mockFactory2" name="fileValidator" class="tests.base.MocksFactory" >
    <property name="type" value="validation.file.FileValidator" />
</bean>
<bean id="mockFactory3" name="documentMatcher" class="tests.base.MocksFactory" >
    <property name="type" value="validation.matching.DocumentMatcher" />
</bean>
<bean id="mockFactory4" name="uploadMatcher" class="tests.base.MocksFactory">
    <property name="type" value="validation.matching.UploadMatcher" />
</bean>
<bean id="mockFactory5" name="tempFileLocalService" class="tests.base.MocksFactory">
    <property name="type" value="service.TempFileLocalService" />
</bean>
<bean id="mockFactory6" name="orderLocalService" class="tests.base.MocksFactory">
    <property name="type" value="service.OrderLocalService" />
</bean>
<bean id="mockFactory7" name="counterLocalService" class="tests.base.MocksFactory">
    <property name="type" value="service.CounterLocalService" />
</bean>

因为没有 id & name 它不会推断类型。

【问题讨论】:

  • This 示例对我来说很酷。

标签: spring mocking autowired


【解决方案1】:

当 XML 文件应该与标准 spring/mockito jar 一起使用时,您可以使用 ProxyFactoryBean,它可以与自动装配一起使用(在 Spring 2.5 上测试)。

<bean id="dao" class="org.springframework.aop.framework.ProxyFactoryBean">
   <property name="target"> <bean class="org.mockito.Mockito" factory-method="mock"> <constructor-arg value="com.package.Dao" /> </bean> </property>
   <property name="proxyInterfaces"> <value>com.package.Dao</value> </property>
</bean> 

【讨论】:

    【解决方案2】:

    我更进一步,在 FactoryBean 中添加了更多代码,并将真正的模拟创建保留在我的测试类中。相反,我的 FactoryBean 在 Spring 启动时根据需要生成动态代理——它不会遇到您所看到的打字问题——并且测试可以根据需要连接到模拟中。我写了一个blog post,描述了如何做到这一点。这篇文章专门讨论了测试 JAX-RS 资源类,但如果您模糊了 JAX-RS 的内容,last section 几乎可以独立作为您尝试的替代方式。

    【讨论】:

    • 它做得很好,但我习惯于只留下一见钟情的解决方案。这需要大量的注意力才能得到它,而且一段时间后其他程序员和我自己都会如此反复:-)
    • @lisak:我喜欢使用它的原因恰恰相反:它让你可以像往常一样继续编写测试,所以没有什么新东西需要习惯。
    【解决方案3】:

    我想到了什么:

    public class SpringMocks implements ApplicationContextAware {
    
        private static final Logger logger = LoggerFactory.getLogger(SpringMocks.class);
        private final List<Class<?>> classes;
    
        public SpringMocks(List<Class<?>> classes) {
            this.classes = classes;
        }
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            if (applicationContext instanceof GenericApplicationContext) {
                GenericApplicationContext context = (GenericApplicationContext) applicationContext;
                DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
    
                for (Class<?> className : classes) {
                    String beanName = RandomStringUtils.randomAlphanumeric(10);
                    Object singletonObject = Mockito.mock(className);
                    beanFactory.registerSingleton(beanName, singletonObject);
                }
            } else {
                logger.warn("unable to add beans to the context!");
            }
        }
    }
    

    以及定义:

    <bean class="com.whatever.SpringMocks">
        <constructor-arg index="0">
            <list>
                <value>com.whatever.enricher.Enricher</value>
                <value>com.whatever.nimbus.NimbusOrderDao</value>
                <value>com.whatever.nimbus.NimbusAllocationDao</value>
                <value>com.whatever.nimbus.NimbusExecutionDao</value>
                <value>com.whatever.nimbus.NimbusBookingInstructionDao</value>
                <value>com.whatever.services.SettingsService</value>
                <value>com.whatever.matchers.utils.CVDataRetriever</value>
            </list>
        </constructor-arg>
    </bean>
    

    希望它能帮助那些正在寻找解决方案的人

    【讨论】:

      猜你喜欢
      • 2014-11-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-20
      • 1970-01-01
      • 2016-02-22
      • 2014-04-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多