首页 新闻 会员 周边 捐助

单元测试的困惑

0
悬赏园豆:20 [已解决问题] 解决于 2008-08-21 19:13
<P>我对单元测试没有什么研究,只是看了很多文章说要单元测试,没什么理论。我现在遇到一个问题</P> <DIV class=cnblogs_code><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><IMG src="http://space.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;Activity&nbsp;:&nbsp;AbstractActivity<BR><IMG id=Codehighlighter1_49_601_Open_Image onclick="this.style.display='none'; document.getElementById('Codehighlighter1_49_601_Open_Text').style.display='none'; document.getElementById('Codehighlighter1_49_601_Closed_Image').style.display='inline'; document.getElementById('Codehighlighter1_49_601_Closed_Text').style.display='inline';" src="http://space.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_49_601_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_49_601_Closed_Text').style.display='none'; document.getElementById('Codehighlighter1_49_601_Open_Image').style.display='inline'; document.getElementById('Codehighlighter1_49_601_Open_Text').style.display='inline';" src="http://space.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN id=Codehighlighter1_49_601_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://space.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_49_601_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://space.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">override</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;Execute(IObjectFactory2&nbsp;applicationContext)<BR><IMG id=Codehighlighter1_132_472_Open_Image onclick="this.style.display='none'; document.getElementById('Codehighlighter1_132_472_Open_Text').style.display='none'; document.getElementById('Codehighlighter1_132_472_Closed_Image').style.display='inline'; document.getElementById('Codehighlighter1_132_472_Closed_Text').style.display='inline';" src="http://space.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_132_472_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_132_472_Closed_Text').style.display='none'; document.getElementById('Codehighlighter1_132_472_Open_Image').style.display='inline'; document.getElementById('Codehighlighter1_132_472_Open_Text').style.display='inline';" src="http://space.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN id=Codehighlighter1_132_472_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://space.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_132_472_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://space.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;applicationContext.Resolve</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">ILog</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">().Debug(</SPAN><SPAN style="COLOR: #800000">"</SPAN><SPAN style="COLOR: #800000">Starting&nbsp;DownloadWebPage</SPAN><SPAN style="COLOR: #800000">"</SPAN><SPAN style="COLOR: #000000">);</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">考虑将此句放入模板方法中</SPAN><SPAN style="COLOR: #008000"><BR><IMG src="http://space.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IResult&nbsp;iresult&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://space.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;applicationContext.Resolve</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IDictionaryAdapterFactory</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">().GetAdapter</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">IResult</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">.TaskId,<BR><IMG src="http://space.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iresult.WebPageSource&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;GetSource(iresult.Url,&nbsp;Encoding.GetEncoding(</SPAN><SPAN style="COLOR: #800000">"</SPAN><SPAN style="COLOR: #800000">UTF-8</SPAN><SPAN style="COLOR: #800000">"</SPAN><SPAN style="COLOR: #000000">),&nbsp;</SPAN><SPAN style="COLOR: #800080">30000</SPAN><SPAN style="COLOR: #000000">);<BR><IMG src="http://space.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://space.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&nbsp;GetSource(</SPAN><SPAN style="COLOR: #0000ff">string</SPAN><SPAN style="COLOR: #000000">&nbsp;url,&nbsp;Encoding&nbsp;encoding,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;timeout)<BR><IMG id=Codehighlighter1_558_594_Open_Image onclick="this.style.display='none'; document.getElementById('Codehighlighter1_558_594_Open_Text').style.display='none'; document.getElementById('Codehighlighter1_558_594_Closed_Image').style.display='inline'; document.getElementById('Codehighlighter1_558_594_Closed_Text').style.display='inline';" src="http://space.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_558_594_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_558_594_Closed_Text').style.display='none'; document.getElementById('Codehighlighter1_558_594_Open_Image').style.display='inline'; document.getElementById('Codehighlighter1_558_594_Open_Text').style.display='inline';" src="http://space.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN id=Codehighlighter1_558_594_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://space.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_558_594_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://space.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&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">null</SPAN><SPAN style="COLOR: #000000">;<BR><IMG src="http://space.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://space.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top><BR><IMG src="http://space.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN></DIV> <P>该类主要有两个方法Execute,GetSource,其中Execute接收外部的对象,然后在内部调用GetSource方法进行处理。对该类进行单元测试,我的想法是,对GetSource进行单元测试,虽然其是私有方法,但是VS2008集成的单元测试工具可以对该方法进行测试,而不用改变其修饰符。这一步完成了。</P> <P>对另一个Execute方法是否要测试,我有些困惑,传入的是一个接口,我考虑使用Mock,可是mock之后,整个方法是执行了,我怎么对它进行测试呢,这个方法是void我要测试什么呢?</P>
问题补充: 可能我对问题描述的不太清楚,GetSource方法,可能测试一下各种边界条件,其输出是否是期望的就可以了(是这样吗?) 那么Execute方法(由于其传入参数是一个Interface,因此我需要隔离它,所以要mock(是这样的逻辑吗?),可是在mock了之后,我要验证什么呢,它没有返回值(这个方法我的理解是肯定要测试,可是我不清楚,单元测试的“度”是什么,要测试什么)
lexus的主页 lexus | 初学一级 | 园豆:0
提问于:2008-08-19 11:08
< >
分享
最佳答案
0
你不应该测试Private的方法,即使微软为你提供了方法。因为,一个方法被定义为Private的,就表示,这个方法不应该被其它人使用。他还有一个隐含的意思:这个方法可能随时被删除和修改。这样的修改不需要通知任何人。 对于你上面的例子,如果你认为GetSource方法的已经很稳定,不会被删除或修改接口。那么,我觉的,你应该抽象一个类似GetSrouceHelper的静态类型,包装这个方法,并且Public它。对这个静态类型单独编写单元测试。 从你上面的程序看,你的Execute方法的实现已经足够的简单了,如果你对GetSource方法已经进行了测试,同时你认为将来Execute方法也不会有什么变化了,并且你对它的实现已经有信心了。就不要写单元测试了。单元测试的一个重要的原则就是:对需要测试的单元进行单元测试。 如果是在要写,可以如下: MockRepository repository = new MockRepository(); IObjectFactory2 factory = repository.CreateMock<IObjectFactory2>(); IDictionaryAdapterFactory adapter = repository.CreateMock<IDictionaryAdapterFactory>(); IResult result = repository.CreateMock<IResult>(); // 这里写期待被调用的代码 Expect.On(factory.Resolve<IDictionaryAdapterFactory>()).Return(adapter); Expect.On(adapter.GetAdapter<IResult>(123/*this.TaskId*/).Return(result); result.WebPageSource = "http://cajon.cnblogs.com/" /*你期望的URL*/; repository.ReplayAll(); // 这里写测试代码 Execute(factory); // 最后校验 repository.VerifyAll(); 看起来很无聊吧?就是因为这个方法确实已经不需要测试了。当然,如果你对IObjectFactory2不放心,那你应该去测试IObjectFactory2,而不是测试这个方法。
Colin Han | 老鸟四级 |园豆:3041 | 2008-08-19 13:02
其他回答(1)
0
void的就测试在不应该抛出异常的时候确实没有抛出异常,在应该抛出异常的时候确实就抛出了你想要的异常 个人不喜欢对非public进行测试,因为我相信只要public的工作正常,private自然没问题,内聚性使然 MOCK确实是这么用的,接下去就看是不是按你的逻辑在走就行了,比如你传个null进去,如果没抛出ArgumentNullException,而抛出了NullReferenceException,就说明你没有对参数做null检测
Gray Zhang | 园豆:17610 (专家六级) | 2008-08-19 11:32
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册