【问题标题】:Should I use a seperate beans.xml configuration for instantiating objects in my unit tests?我应该在单元测试中使用单独的 beans.xml 配置来实例化对象吗?
【发布时间】:2015-03-24 03:33:05
【问题描述】:

这是我的应用程序的 Beans.xml

<?xml version="1.0" encoding="UTF-8"?>

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


        <bean id="myRoom" class="org.world.hello.Room">
            <property name="bottleCounter">
                <bean id="myBottleCounter" class="org.world.hello.BottleCounter" />
            </property>
            <property name="numBottles" value="10"></property>

        </bean>    
</beans>

这是一个Room bean,它具有BottleCounter bean 作为属性。

现在,我想为BottleCounter 编写一个单元测试。

public class BottleCounterTest {

    ApplicationContext context; 

    @Before
    public void setUp()
    {
        context = new ClassPathXmlApplicationContext("Beans.xml");      
    }

    @Test
    public void testOneBottle() {

        BottleCounter bottleCounter = (BottleCounter) context.getBean("myBottleCounter");

        assertEquals("1 bottles of beer on the wall1 bottles of beer!", bottleCounter.countBottle(1));
    }

}

但是我不能直接引用myBottleCounter,因为它是一个内部bean?并给我No bean named 'myBottleCounter' is defined

那么,我应该在单独的 xml 中定义我的测试 bean 吗?

例如。

testBeans.xml

<?xml version="1.0" encoding="UTF-8"?>

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


        <bean id="testRoom" class="org.world.hello.Room">
            <property name="bottleCounter">
                <bean id="myBottleCounter" class="org.world.hello.BottleCounter" />
            </property>
            <property name="numBottles" value="3"></property>

        </bean>

        <bean id="testBottleCounter" class="org.world.hello.BottleCounter" />



</beans>

BottleCounterTest.java

public class BottleCounterTest {

    ApplicationContext context; 

    @Before
    public void setUp()
    {
        context = new ClassPathXmlApplicationContext("testBeans.xml");      
    }

    @Test
    public void testOneBottle() {

        BottleCounter bottleCounter = (BottleCounter) context.getBean("testBottleCounter");

        assertEquals("1 bottles of beer on the wall1 bottles of beer!", bottleCounter.countBottle(1));
    }

}

【问题讨论】:

    标签: spring unit-testing instantiation


    【解决方案1】:

    你可以这样做:

    Room room = (Room) context.getBean("myRoom");
    BottleCounter bottleCounter = room.getBottleCounter();
    

    或者,如果您可以修改 XML 文件,则单独声明 BottleCounter bean。

    <bean id="testRoom" class="org.world.hello.Room">
        <property name="bottleCounter">
            <ref bean="myBottleCounter"/>
        </property>
        <property name="numBottles" value="3"></property>
    
    </bean>
    
    <bean id="myBottleCounter" class="org.world.hello.BottleCounter" />
    

    【讨论】:

    • 我不喜欢第一个解决方案的地方是,测试需要知道生产结构是什么。我们的测试只是想测试 BottleCounter 是否正常工作。它不需要知道 Room 拥有它。
    • 第二种解决方案更好,但请参阅我对给出的其他答案的批评。
    • 是的,我在第一个解决方案上看到了您的 cmets,因此我推荐了第二个解决方案。
    • 我的意思是我对 Manish 的回答的评论。
    【解决方案2】:

    推荐的方法是:

    <bean id="myBottleCounter" class="org.world.hello.BottleCounter" />
    
    <bean id="testRoom" class="org.world.hello.Room">
      <property name="bottleCounter">
        <ref bean="myBottleCounter"/>
      </property>
      <property name="numBottles" value="3"></property>
    </bean>
    
    @ContextConfiguration(locations = "classpath:Beans.xml")
    @RunWith(SpringJUnit4ClassRunner.class)
    public class BottleCounterTest {
      @Autowired
      BottleCounter bottleCounter;
    
      @Test
      public void testOneBottle() {
        assertEquals("1 bottles of beer on the wall1 bottles of beer!", bottleCounter.countBottle(1));
      }
    }
    

    总而言之,您明确声明 bean BottleCounter 的一个实例,然后使用 Spring 将其注入您的测试类中。

    确保在运行测试时spring-test.jar 在类路径中。

    【讨论】:

    • 我不喜欢这个解决方案的一点是,它很难看到内部和外部 bean 的内容/关系。你有 10 个不同的房间,都有不同的 BottleCounters?我认为在 XML 中定义内部 bean 很清楚。
    • 然后保留你的内部bean并独立声明一个单独的用于测试。如果您使用的是 Maven,您也可以在 src\test\resources 中拥有一个 Spring 应用程序上下文初始化文件(例如,TestBeans.xml)并将此文件用于您的测试。这个文件的内容可以简单到&lt;bean class="org.world.hello.BottleCounter" /&gt;。我的观点是,既然已经在使用 Spring,那么它也应该用于测试用例。
    猜你喜欢
    • 2016-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-07
    • 2023-03-09
    • 2014-06-11
    • 2010-11-23
    • 2011-01-01
    相关资源
    最近更新 更多