﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-子在川上曰-随笔分类-Test</title><link>http://www.blogjava.net/chengang/category/8414.html</link><description>　　　　逝者如斯乎不舍昼夜</description><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 06:42:49 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 06:42:49 GMT</pubDate><ttl>60</ttl><item><title>有配置文件有关的测试</title><link>http://www.blogjava.net/chengang/archive/2006/03/29/38062.html</link><dc:creator>陈刚</dc:creator><author>陈刚</author><pubDate>Wed, 29 Mar 2006 07:42:00 GMT</pubDate><guid>http://www.blogjava.net/chengang/archive/2006/03/29/38062.html</guid><wfw:comment>http://www.blogjava.net/chengang/comments/38062.html</wfw:comment><comments>http://www.blogjava.net/chengang/archive/2006/03/29/38062.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/chengang/comments/commentRss/38062.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chengang/services/trackbacks/38062.html</trackback:ping><description><![CDATA[问题：<br />一个系统有一些信息放在一个XML文件中，由于此XML文件会经常变动，所以写Test Case不能依赖此XML文件，否则在使用中每一次XML正常的变动都会导致TestCase出错。那么该如何测试呢。<br /><br />解决方案一：<br />将XML的内容用字符串的方式写在TestCase中。如下所示，这个TestCase主要是测试ViewXMLParser这个类的parse方法，这个方法的作用是将XML配置文件中的信息转化成一个个的Bean。<br /><br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.io.ByteArrayInputStream;<br /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.io.InputStream;<br /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.util.List;<br /><br /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> junit.framework.TestCase;<br /><br /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> org.dom4j.Document;<br /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> org.dom4j.DocumentException;<br /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> org.dom4j.Element;<br /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> org.dom4j.io.SAXReader;<br /><br /></span><span style="COLOR: #008000">/**</span><span style="COLOR: #008000"><br /> * </span><span style="COLOR: #808080">@author</span><span style="COLOR: #008000"> chengang 2006-3-6<br /> </span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> TestViewParser </span><span style="COLOR: #0000ff">extends</span><span style="COLOR: #000000"> TestCase {<br />    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> String xml1;<br />    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> String xml2;<br /><br />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> TestViewParser() {<br />        {<br />            </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">一个完整的测试,及测试可选项</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">            StringBuffer sb </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> StringBuffer();<br />            sb.append(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;?xml version=\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">1.0</span><span style="COLOR: #000000">\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> encoding=\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">GB2312\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">?&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />            sb.append(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;jmxui&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />            sb.append(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">     &lt;views&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />            sb.append(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">       &lt;view id=\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">LogTestView\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />            sb.append(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">             &lt;operation name=\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">storeConfig1\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />            sb.append(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">             &lt;attributes&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />            sb.append(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">                   &lt;attribute name=\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">times\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> description=\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">时间值\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />            sb.append(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">                   &lt;attribute name=\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">logs\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> description=\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">日志数\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />            sb.append(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">             &lt;/attributes&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />            sb.append(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">       &lt;/view&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />            sb.append(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">       &lt;view id=\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">LogConfigView\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> class=\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">com.wxxr.management.admin.console.jmx.custom.ui.CustomComposite\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />            sb.append(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">     &lt;/views&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />            sb.append(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;/jmxui&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />            xml1 </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> sb.toString();<br />        }<br />        {<br />            </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">测试特别情况</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">            StringBuffer sb </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> StringBuffer();<br />            sb.append(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;?xml version=\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">1.0</span><span style="COLOR: #000000">\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> encoding=\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">GB2312\</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">?&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />            sb.append(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;jmxui&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />            sb.append(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">     &lt;views&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />            sb.append(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">     &lt;/views&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />            sb.append(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;/jmxui&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />            xml2 </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> sb.toString();<br />        }<br />    }<br /><br />    </span><span style="COLOR: #008000">/*</span><span style="COLOR: #008000"><br />     * Test method for 'com.wxxr.management.admin.console.jmx.custom.JmxXmlReader.getGroupNodes()'<br />     </span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> testParse() </span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> Exception {<br />        Element viewsElement </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> getViewsElement(xml1);<br />        List</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">ViewBean</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> list </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> ViewXMLParser().parse(viewsElement);<br />        assertEquals(</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">, list.size());<br />        {<br />            ScriptViewBean bean </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (ScriptViewBean) list.get(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">);<br />            assertEquals(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">LogTestView</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, bean.getId());<br />            assertEquals(ScriptComposite.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">.getName(), bean.getViewClass());<br />            assertEquals(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">org.jnp.interfaces.NamingContextFactory</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, node.getFactory());<br />            assertEquals(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">jnp://localhost:1099</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, node.getUrl());<br />            assertEquals(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">jmx/rmi/RMIAdaptor</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, node.getJndi());<br />        }<br />        {<br />            CustomViewBean bean </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (CustomViewBean) list.get(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br />            assertEquals(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">LogConfigView</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, bean.getId());<br />            assertEquals(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">com.wxxr.management.admin.console.jmx.custom.ui.CustomComposite</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, bean.getViewClass());<br />        }<br />    }<br /><br />    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> Element getViewsElement(String xml) {<br /><font style="BACKGROUND-COLOR: #ff0000">        InputStream inputStream </font></span><font style="BACKGROUND-COLOR: #ff0000"><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span></font><span style="COLOR: #000000"><font style="BACKGROUND-COLOR: #ff0000"> ByteArrayInputStream(xml.getBytes());<br /></font>        Document doc </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">;<br />        </span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000"> {<br />            SAXReader reader </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> SAXReader();<br />            doc </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> reader.read(inputStream);<br />        } </span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000"> (DocumentException e) {<br />            e.printStackTrace();<br />        }<br /><br />        Element root </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> doc.getRootElement();<br />        Element viewsElement </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> root.element(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">views</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br />        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> viewsElement;<br />    }<br /><br />}</span></div><br />说明：<br />（1）将XML写在一个String里。<br />（2）InputStream inputStream <span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> ByteArrayInputStream(xml.getBytes());是关键，这是用一个string生成一个InputStream，这样就能替代读取XML文件的效果。<br /></span><img src ="http://www.blogjava.net/chengang/aggbug/38062.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chengang/" target="_blank">陈刚</a> 2006-03-29 15:42 <a href="http://www.blogjava.net/chengang/archive/2006/03/29/38062.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用IoC模式使类更易于测试</title><link>http://www.blogjava.net/chengang/archive/2006/03/14/35200.html</link><dc:creator>陈刚</dc:creator><author>陈刚</author><pubDate>Tue, 14 Mar 2006 03:27:00 GMT</pubDate><guid>http://www.blogjava.net/chengang/archive/2006/03/14/35200.html</guid><wfw:comment>http://www.blogjava.net/chengang/comments/35200.html</wfw:comment><comments>http://www.blogjava.net/chengang/archive/2006/03/14/35200.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/chengang/comments/commentRss/35200.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chengang/services/trackbacks/35200.html</trackback:ping><description><![CDATA[<DIV><BR>文/陈刚 from <A href="http://blog.chengang.com.cn">http://blog.chengang.com.cn</A>&nbsp; <BR><BR>有一个需要被测试的类如下：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;ViewManager&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">static</SPAN><SPAN style="COLOR: #000000">&nbsp;XmlBeanFactory&nbsp;factory&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;Context.getInstance().getXmlBeanFactory();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;View&nbsp;getView(String&nbsp;viewId)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">ViewBean</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;list&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;factory.getViews();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">&nbsp;(ViewBean&nbsp;bean&nbsp;:&nbsp;list)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(bean.getId().equals(viewId))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;bean.getView();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;NullComposite();<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>｝</SPAN></DIV><BR><BR><STRONG>问题：如果要测试getView方法该怎么办呢？<BR></STRONG><BR>显然由于此方法依赖于factory（XmlBeanFactory ），XmlBeanFactory 内含有比较复杂的逻辑，而且还要读取XML文件，这导致getView不可能被单独测试（一个单元测试的要点：简单独立，一次只测试一个类）。为了让ViewManager能剔除掉XmlBeanFactory，而被单独测试，我们需要做一些改变－－让XmlBeanFactory由外界注入，这样就可以写一个逻辑简单的Mock类来替代XmlBeanFactory，实现ViewManager的单独测试。具体实现的方法是加一个构造函数，让XmlBeanFactory可以通过构造函数注入，当然为了保持原有代码的兼容性，默认的factory也不可少。代码如下：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;ViewManager&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">static</SPAN><SPAN style="COLOR: #000000">&nbsp;XmlBeanFactory&nbsp;factory;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;ViewManager()&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;factory&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;Context.getInstance().getXmlBeanFactory();</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">默认的factory</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;ViewManager(XmlBeanFactory&nbsp;factory)&nbsp;{</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">注入的factory</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">.factory&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;factory;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;View&nbsp;getView(String&nbsp;viewId)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">ViewBean</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;list&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;factory.getViews();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">&nbsp;(ViewBean&nbsp;bean&nbsp;:&nbsp;list)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(bean.getId().equals(viewId))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;bean.getView();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;NullComposite();<BR>&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></DIV><BR>测试的代码如下：<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;TestViewManager&nbsp;</SPAN><SPAN style="COLOR: #0000ff">extends</SPAN><SPAN style="COLOR: #000000">&nbsp;TestCase&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;ViewManager&nbsp;viewManager;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;@Override<BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">protected</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;setUp()&nbsp;</SPAN><SPAN style="COLOR: #0000ff">throws</SPAN><SPAN style="COLOR: #000000">&nbsp;Exception&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">super</SPAN><SPAN style="COLOR: #000000">.setUp();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;viewManager&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;ViewManager(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;MockXmlBeanFactory());<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;testGetView()&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;View&nbsp;v&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;viewManager.getView(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">viewId002</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertEquals(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">viewId002</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;v.getViewId());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertEquals(CustomView.</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">,&nbsp;v.getClass());<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;testGetViewByNoneId()&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;View&nbsp;v&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;viewManager.getView(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">abc</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertEquals(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">abc</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;v.getViewId());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertEquals(NullComposite.</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">,&nbsp;v.getClass());<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">static</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;MockXmlBeanFactory&nbsp;</SPAN><SPAN style="COLOR: #0000ff">extends</SPAN><SPAN style="COLOR: #000000">&nbsp;XmlBeanFactory&nbsp;{ //XmlBeanFactory&nbsp;的Mock类<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;List</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">ViewBean</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;getViews()&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">ViewBean</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;views&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;ArrayList</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">ViewBean</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;views.add(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;CustomViewBean(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">viewId001</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;NullComposite.</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">.getName()));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;views.add(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;CustomViewBean(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">viewId002</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;CustomView.</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">.getName()));<BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;views;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>}<BR></SPAN></DIV><BR>在测试的时候报错了，错在assertEquals(<SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">abc</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;v.getViewId());。一查是没有把viewId赋给NullComposite对象。纠正错误的办法是：把ViewManager&nbsp;的getView的方法最后一句改为<SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;NullComposite(viewId);。</SPAN>这是一个很隐蔽的BUG，以后在这里出问题可真够你花时间找的，现在一下子就测试出来了，这就是测试的好处吧。<BR></SPAN></DIV><img src ="http://www.blogjava.net/chengang/aggbug/35200.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chengang/" target="_blank">陈刚</a> 2006-03-14 11:27 <a href="http://www.blogjava.net/chengang/archive/2006/03/14/35200.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JUnit中如何测试异常</title><link>http://www.blogjava.net/chengang/archive/2006/03/07/34068.html</link><dc:creator>陈刚</dc:creator><author>陈刚</author><pubDate>Tue, 07 Mar 2006 06:40:00 GMT</pubDate><guid>http://www.blogjava.net/chengang/archive/2006/03/07/34068.html</guid><wfw:comment>http://www.blogjava.net/chengang/comments/34068.html</wfw:comment><comments>http://www.blogjava.net/chengang/archive/2006/03/07/34068.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/chengang/comments/commentRss/34068.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chengang/services/trackbacks/34068.html</trackback:ping><description><![CDATA[<DIV class=item-content>2005-11-04<BR><BR>　　 很多时候，我们要写一些单元测试来测试我们程序是否能正确触发异常。比如下面的例子中，我们就写了一个test case来测试一个Email验证类EmailAddrValidator，这个类有一个doValidate(email)方法可以验证email是否合法，如果不合法则会抛出ValidationException异常。因此我们写了两个方法来进行单元测试，前一个方法testDoValidate用来测试正常值，后一个方法testDoValidateException用来测试对错误的email格式是否能正确触发异常。<BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">import junit.framework.TestCase;<BR><BR>public class TestEmailAddrValidator extends TestCase {<BR>&nbsp;&nbsp;&nbsp; EmailAddrValidator validator = new EmailAddrValidator();<BR><BR>&nbsp;&nbsp;&nbsp; public void testDoValidate() throws ValidationException {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; validator.doValidate("glchengang@163.com", null);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; validator.doValidate("glchen.gang@163.com", null);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; validator.doValidate("glchen_gang@163.com", null);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; validator.doValidate("glchen.gang@163_tom.com", null);<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; public void testDoValidateException() {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testDoValidateException("@b.c");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testDoValidateException("a@.c");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testDoValidateException("a@b.");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testDoValidateException("@.c");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testDoValidateException("@...");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testDoValidateException(" ");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testDoValidateException(null);<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; private void testDoValidateException(String email) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; validator.doValidate(email, null);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fail("末抛出异常");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (ValidationException e) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assertTrue(true);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }<BR>}</DIV>
<P>例程说明: 这个例子的关键是方法testDoValidateException(String email) 。<BR></P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">import java.util.Locale;<BR>import com.hygensoft.common.configure.ConfigureObject;<BR><BR>public class EmailAddrValidator{<BR><BR>&nbsp;&nbsp;&nbsp; protected static final String ERROR_CODE_INVALID_EMAIL_ADDR = "INVALID_EMAIL_ADDR";<BR>&nbsp;&nbsp;&nbsp; protected static final String ERROR_CODE_INVALID_INPUT = "INVALID_INPUT_OBJECT";<BR><BR>&nbsp;&nbsp;&nbsp; public Object doValidate(Object input, Locale locale) throws ValidationException {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!(input instanceof String)) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new ValidationException(ERROR_CODE_INVALID_INPUT, input);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String inputStr = (String) input;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int idx = inputStr.indexOf('@');<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (idx == -1 || idx == 0) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new ValidationException(ERROR_CODE_INVALID_INPUT, input);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int idx2 = inputStr.indexOf('.', idx);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (idx2 == -1 || idx2 == idx + 1) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new ValidationException(ERROR_CODE_INVALID_INPUT, input);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (inputStr.endsWith(".")) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new ValidationException(ERROR_CODE_INVALID_INPUT, input);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return input;<BR>&nbsp;&nbsp;&nbsp; }<BR><BR>&nbsp;&nbsp;&nbsp; /* (non-Javadoc)<BR>&nbsp;&nbsp;&nbsp;&nbsp; * @see com.hygensoft.common.configure.Configurable#initialize(com.hygensoft.common.configure.ConfigureObject)<BR>&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp; public void initialize(ConfigureObject conf) {}<BR><BR>}</DIV>
<P><BR>例程说明：在这里Locale 参数并没有用到。</P>
<DIV class=clear></DIV></DIV><img src ="http://www.blogjava.net/chengang/aggbug/34068.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chengang/" target="_blank">陈刚</a> 2006-03-07 14:40 <a href="http://www.blogjava.net/chengang/archive/2006/03/07/34068.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于单元测试的讨论</title><link>http://www.blogjava.net/chengang/archive/2006/03/07/34064.html</link><dc:creator>陈刚</dc:creator><author>陈刚</author><pubDate>Tue, 07 Mar 2006 06:34:00 GMT</pubDate><guid>http://www.blogjava.net/chengang/archive/2006/03/07/34064.html</guid><wfw:comment>http://www.blogjava.net/chengang/comments/34064.html</wfw:comment><comments>http://www.blogjava.net/chengang/archive/2006/03/07/34064.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/chengang/comments/commentRss/34064.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chengang/services/trackbacks/34064.html</trackback:ping><description><![CDATA[<DIV><SPAN>今天收到javaeye的一个有回复通告的邮件，一查原来是一个很久以前的帖子又人回复了。帖子原地址如下：</SPAN><SPAN><A href="http://forum.javaeye.com/viewtopic.php?p=110113#110113">http://forum.javaeye.com/viewtopic.php?p=110113#110113</A>　</SPAN></DIV>
<DIV><SPAN></SPAN></DIV>
<DIV><SPAN>　</SPAN></DIV>
<DIV><SPAN></SPAN></DIV>
<DIV><SPAN></SPAN></DIV>
<DIV><SPAN>－－－－－－－下面的是顶帖：－－－－－－－－－－－－－－－</SPAN><SPAN></SPAN></DIV>
<DIV><SPAN></SPAN></DIV>
<DIV><SPAN>当项目进展到一定程度，也会产生出大量的单元测试代码。而且这些单元测试代码也被不断的增加、修改和删除。渐渐单元测试代码也变得难以维护了，里边夹杂了太多的业务逻辑。创建一个新的测试要做很多初始化的工作，很难在ide里直接运行所有测试，很难单独运行某项测试，运行所有的单元测试要比较长的时间...... <BR><BR>我想了下，造成这种现象的原因有以下几种： <BR>1.未及时对单元测试进行重构，删除不必要的测试，合并类似的测试。 <BR>2.单元测试粒度过大，造成测试类过于臃肿。应该把大粒度的测试抽出来单独作为功能测试运行。 <BR>3.大量依赖外界环境，如数据库。应使用mock object解除依赖关系。 </SPAN></DIV>
<DIV><SPAN></SPAN></DIV>
<DIV><SPAN>　</SPAN> 
<DIV><SPAN></SPAN></DIV>
<DIV><SPAN>－－－－－我对此帖的一点看法：－－－－－－－－－－－－－－</SPAN></DIV>
<DIV><SPAN>这个帖的楼主对单元测试显示理解有偏颇。</SPAN></DIV>
<DIV><SPAN>　</SPAN></DIV>
<DIV><SPAN>（1）“里边夹杂了太多的业务逻辑”，单元测试怎么能夹杂业务逻辑呢？！！！单元测试代码是用来测试业务逻辑的，楼主怎么还加入什么业务逻辑。单元测试应该尽量的简单和独立，简单性和独立性是单元测试代码的原则。细粒度是实现单元测试代码简单性和独立性的方法。</SPAN></DIV>
<DIV><SPAN>　</SPAN></DIV>
<DIV><SPAN></SPAN></DIV>
<DIV><SPAN>单元测试的目的是为了让我们今后维护时能更快的定位BUG，所以简单独立测试代码更易读、更利于这个目的。如果阅读一个单元测试代码要超过十分钟，我觉得这个单元测试就算是失败的。</SPAN></DIV>
<DIV><SPAN></SPAN></DIV>
<DIV><SPAN>　</SPAN></DIV>
<DIV><SPAN></SPAN></DIV>
<DIV><SPAN>（2）“创建一个新的测试要做很多初始化的工作”，其根本原因是在于楼主的单元测试做法有误，"单元测试粒度过大，造成测试类过于臃肿"，“大量依赖外界环境，如数据库”。</SPAN></DIV>
<DIV><SPAN></SPAN></DIV>
<DIV><SPAN>千万不要写类似这样的单元测试代码：[输入一个数据，然后数据经过业务逻辑处理，而经过Hibernate进入数据库，然后单元测试从数据库读出数据来看看数据是否正确]，这样的写单元测试的思路是根本错误的。试想，如果运行测试时出错，你就很难从如此庞大混杂的代码中定位问题是出在业务逻辑层面、还是中间层、还是数据存储层。</SPAN></DIV>
<DIV><SPAN>　</SPAN></DIV>
<DIV><SPAN></SPAN></DIV>
<DIV><SPAN>千万不要写上面那种一杆子捅到底的测试代码。</SPAN><SPAN>你应该这样，针对[数据经过业务逻辑的处理]来写一个单元测试。只针对最复杂和最核心的逻辑来写单元测试，减少了单元测试代码的数量，也就减少了对测试代码本身的维护量。有一些不应该由单元测试来做的工作，还是留到集成测试和测试员的beta版测试吧。</SPAN></DIV>
<DIV><SPAN>　</SPAN></DIV>
<DIV><SPAN></SPAN></DIV>
<DIV><SPAN>（3）单元测试要尽量做到环境无关性。比如测试EJB的单元测试，运行它并不需要启动Weblogic等EJB容器才能测试的，因为我们主要是测试它的业务逻辑，业务逻辑和weblogic容器是无关的。要实现这个目的，也就要求我们在写代码时要把业务逻辑写得更单纯，让它和容器相关的代码分离开来。</SPAN></DIV>
<DIV><SPAN>　</SPAN></DIV>
<DIV><SPAN></SPAN></DIV>
<DIV><SPAN>数据库也是一个常见的环境无关性问题，我们必须让单元测试脱离数据库（也就是脱离环境）而能运行。解决的方法是：我们可以写一个假(mock)的数据库，这是很简单的：一个类加几个List变量就可以模拟库和表了。</SPAN></DIV>
<DIV><SPAN>　</SPAN></DIV>
<DIV><SPAN>　</SPAN></DIV></DIV>
<DIV>-----------另一个帖子回道: -----------------------<BR>小规模的项目和试验性项目才可能搞搞这么频繁的单元测试，大的项目从项目规模，时间上都不太现实 </DIV>
<DIV>　</DIV>
<DIV>-----------我的看法和回复: -----------------------</DIV>
<DIV>如果你维护过大项目，你就不会说这样的话了。 <BR>（1）没有单元测试，你无法重构，因为你不知道你的修改是否正确。 <BR>（2）没有单元测试，你出错后，你无法最快的定位BUG所在。并且在修改BUG后，你无法得知自己的修改是否影响到了其他模块。 <BR>（3）没有单元测试，你很难进行需求的修改。 </DIV>
<DIV></DIV>
<DIV>总之一句话：没有单元测试，就很难对代码做修改。所以说小项目可以没有单元测试代码，但大项目一定要有，不然没法维护。另外，单元测试代码逻辑简单，写起来并不是想想中的那样耗时。<BR></DIV><img src ="http://www.blogjava.net/chengang/aggbug/34064.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chengang/" target="_blank">陈刚</a> 2006-03-07 14:34 <a href="http://www.blogjava.net/chengang/archive/2006/03/07/34064.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>