5

我有一个多模块项目,其中每个模块都有自己的单元测试,并为该模块的类提供模拟。

我正在尝试构建一个应用程序上下文,其中每个模块都可以定义自己的模拟,但以后的单元测试将能够覆盖这些模拟,例如:

public class Test {

    private static final class StupidMock {
    }

    @org.junit.Test
    public void test() {
        StaticApplicationContext applicationContext = new StaticApplicationContext();
        final ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
        StupidMock stupidMock = new StupidMock();  // original mock
        beanFactory.registerSingleton(StupidMock.class.getName(), stupidMock);

        StupidMock f1 = applicationContext.getBean(StupidMock.class);
        if (f1 == null || f1 != stupidMock) {  // ensuring mock is retrievable
            fail("Could not get bean");
        }

        for (String names2Remove : beanFactory.getBeanNamesForType(StupidMock.class)) {
            applicationContext.removeBeanDefinition(names2Remove);  // <-- fails here 
        }

        StupidMock stupidMock2 = new StupidMock();     // replacement mock
        beanFactory.registerSingleton(StupidMock.class.getName(), stupidMock2);
    }
}

问题是这个简单的片段在尝试删除第一个模拟时失败,声称没有这样的 bean(尽管 Spring 刚刚成功地为我提供了一个名称)。

如果我只是尝试在第一个模拟之上注册另一个模拟,Spring 会抱怨说已经有对象绑定。

DefaultSingletonBeanRegistry有一个removeSingleton受保护的方法,但我无法控制StaticApplicationContext. 无论如何,我都可以使用反射并调用这个受保护的方法,但是对于这样一个简单的任务来说这样做是错误的。

我究竟做错了什么?我怎样才能实现单例替换StaticApplicationContext

4

3 回答 3

3

这里的问题是 registerSingleton 方法实际上并没有创建相应的BeanDefinition,它只是注册实例化的单例,将其与您提供的名称相关联,并稍后通过应用程序上下文检索它 - 虽然它没有 BeanDefinition 底层。

因此,当您调用时,applicationContext.removeBeanDefinition(names2Remove);它会失败,因为没有bean 定义,只有注册的完全实例化的 bean。

解决方法是不使用 registerSingleton,而是使用一种使用 BeanDefinition 的 registerSingleton 形式:

Map<String, String> map = new HashMap<String, String>();
map.put("i", "10"); // set all the properties for the mock..
MutablePropertyValues propertyValues = new MutablePropertyValues(map);

beanFactory.registerSingleton(StupidMock.class.getName(), StupidMock.class, propertyValues);
于 2012-07-19T17:59:26.570 回答
2

您可以使用spring-reinject重新定义 bean 。

于 2014-02-02T18:04:45.350 回答
1

如果您使用的是 Spring 框架,为什么不使用Spring 测试框架

您可以使用以下注释在每个单元测试的基础上进行特定的模拟

@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
于 2012-07-19T16:37:04.957 回答