实践篇,不多说,上代码,本书摘自Spring实战。
1、接口Quest
public interface Quest {
public void emback();
}
Quest的实现类SlayDragonQuest
public class SlayDragonQuest implements Quest {
private PrintStream printStream;
public SlayDragonQuest(PrintStream printStream) {
this.printStream = printStream;
}
@Override
public void emback() {
printStream.println("Slay Dragon Quest");
}
}
2、接口Knight
public interface Knight {
public void embackQuest();
}
Knight的实现类BraveKnight
public class BraveKnight implements Knight {
private Quest quest;
/** 构造注入 */
public BraveKnight(Quest quest) {
this.quest = quest;
}
@Override
public void embackQuest() {
quest.emback();
}
}
3、对BraveKnight 进行Mock测试:
public class BraveKnightTest {
//mock测试,可以用mock(Quest.class)方法模拟生成Quest的实例,而不需要真的创建其实现类。并且mock测试运行很快,直接看运行结果是否
@Test
public void testEmbackQuest() {
//given(入参)
Quest mockQuest = mock(Quest.class);
BraveKnight braveKnight = new BraveKnight(mockQuest);
//when(条件)
braveKnight.embackQuest();
//then(出参)
//验证调用mockQuest的emback()方法1次
verify(mockQuest, times(1)).emback();
}
//单元测试,直接在输出窗口打印结果 :Slay Dragon Quest
@Test
public void testEmbackQuest1() {
Quest quest = new SlayDragonQuest(System.out);
BraveKnight braveKnight = new BraveKnight(quest);
braveKnight.embackQuest();
}
}
以后遇到其他的项目也可用类似的mock测试,到那时候你就会发现mock 测试挺快的。因为JUnit是单元测试框架,可以轻松的完成关联依赖关系少或者比较简单的类的单元测试,但是对于关联到其它比较复杂的类或对运行环境有要求的类的单元测试,模拟环境或者配置环境会非常耗时,实施单元测试比较困难。
4、问题:BraveKnight 构造方法里边引用了Quest,如何用Spring IOC管控这些类?
其实有三种方法:这里只讲xml方法,以后有时间写一篇这样的博客。创建一个knight.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"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="quest" class="com.cs.model.SlayDragonQuest">
<constructor-arg value="#{T(System).out}"></constructor-arg>
</bean>
<bean id="knight" class="com.cs.model.BraveKnight">
<constructor-arg ref="quest"></constructor-arg>
</bean>
</beans>
会不会很疑惑:这样用xml配置之后该如何使用?
public class KnightMain {
public static void main(String[] args) {
//加载xml
ClassPathXmlApplicationContext applicationContext =
new ClassPathXmlApplicationContext("Knight.xml");
Knight knight = applicationContext.getBean(Knight.class);
knight.embackQuest();
applicationContext.close();
}
}
运行结果:
八月 30, 2018 6:35:38 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@7f690630: startup date [Thu Aug 30 18:35:38 CST 2018]; root of context hierarchy
八月 30, 2018 6:35:38 下午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@351d0846: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,knightConfig,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,knight,quest,minstrel]; root of factory hierarchy
Slay Dragon Quest
八月 30, 2018 6:35:38 下午 org.springframework.context.support.AbstractApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@7f690630: startup date [Thu Aug 30 18:35:38 CST 2018]; root of context hierarchy
八月 30, 2018 6:35:38 下午 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
信息: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@351d0846: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,knightConfig,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,knight,quest,minstrel]; root of factory hierarchy
可以看出其打印了Slay Dragon Quest,即运行成功。