最近MVC项目做单元测试,做的有点晕了。
网上看到这点:单元测试是最小的测试单元了,就是针对一个方法的。
假设一个场景:类AB中有 A方法里调用了B方法,如下:
public class AB { public bool A(bool isSuccess) { B(); return isSuccess; } public void B() { } }
现在 要针对方法A 进行单元测试。
[TestMethod()] public void ATest() { AB ab = new AB(); bool result = ab.A(true); Assert.AreEqual(true, result); }
疑问:
1.A方法调用了B方法,如果B方法发生异常,导致A方法的单元测试没有通过,
这种情况下单元测试失败了,是否能说明A方法有问题?(我觉的A方法本身没有问题,是B方法的问题)
2.如果发生上面的情况,单元测试,其实并没有测试出是B方法的问题,实际项目中,一个方法里跟N多对象和方法有关,这样的单元测试是不是没有什么意义,它找不出具体的问题出在哪里,要单元测试何用?
3. 想到 电灯和 开关的例子,要测试电灯是否是好的,首先要保证开关是好的,如果开关都不能保证好的,灯没亮,就不知道是灯的问题还是开关的问题。
同理,如果B方法不能保证能正常通过,那么说单元测试A方法将没有用,或者说A方法是不可测试的,可不可以这样说?
4.Mock对象就是模拟对象,模拟环境,我对这个Mock对象的理解是去模拟那些可能会导致失败的外部环境。如A方法,依赖B方法,Mock对象应该去模拟B方法,如果模拟不了,就是说A方法可测试性差,或者不能测试。 不知道能不能这样理解? (如果真是这样的话,那就是好多方法都无法单元测试了)
望各位园友 指点一下,在这谢谢啦!
问题:哪些对象需要 去Mock模拟?
答案:1.依赖的对象有风险(导致错误,导致失败);2.依赖的对象方法可能要操作数据库,将花大量的时间,这种代价比较大的。
如果符合这两条中的一条,就应该去 模拟。
对哪些地方要使用Mock等对象,不知道我的理解对不对?还有其它的 请补充
其实你已经差不多找到问题的原因了.对这就是A方法可测试性差,它绝对依赖于B方法的具体实现.而不是它的抽象.
可测试性也是代码好坏的其中一个标准.很多不选择Web Form的原因也是它的可测试性差.当代码可测试性差时,你在单元测试里怎么搞也是没用的.
所以这时应该是重构,使其有更好的可测试性.
至于具体你上面的方法,不明白你为什么要在A里调用一个void的方法.所有也没有更好的重构建议.
只是产生一个依赖关系,没有考虑到 void,能不能根据我的问题 一个个 具体说说
@Qlin:
所有问题我的回答都一样,可测试性好的代码是不应该出现这些问题的.
单元测试就应该关注单个方法内的逻辑.
@zhangweiwen:
我不是写了我的理解不,那我认为的 结论 都是正确的?
@Qlin:
你所有的问题和理解都是建立在一个"可测试性差"的前提上的,所以我觉得你的问题和理解都没有意义.
@zhangweiwen:
这里只是假设一个 外部影响的方法,真实 编程中,你可以看成是抽象,我想知道,我这样去理解单元测试是不是正确的。
@Qlin:
如果是一个抽象的话,就可以使用桩对象来保证不会失败了,怎么会存在那些问题呢?
@zhangweiwen:
谢谢,看看 我的补充问题
@Qlin:
你的理解对的,外部依赖都应该使用使用桩对象或者模拟对象来代替,因为我们要做的是单元测试,只关注单元(方法)本身.
如果单元测试不能解决这样的问题,那么单元测试的实用性就很差了吧……
坐等大牛……
不晓得 我的问题 是不是 太幼稚了
@Qlin: 不是幼稚……我理解的单元测试:测试单一功能,如果有其他因素影响这个方法,那就应该先把其他因素排除,怎么排除呢,我认为单元测试应该包含一段代码,类似测试前准备,以保证排除其他因素,所以单元测试代码总比代码多……
是不是这么理解呢?
ASP.NET MVC单元测试最佳实践
http://www.cnblogs.com/JeffreyZhao/archive/2009/02/23/mvc-unit-test-best-practices.html
谢谢,看完,没有谈到 我的问题啊
问题一:A方法还是有问题,因为作为一个测试只有通过了才算成功,不管什么原因造成失败都是失败。
问题二:单元测试是面向需求的,比如我的站点有个api,那么这个api的所有测试我会单独分出来,这里api里面调用了下面好多东西,每个不同的服务都有自己的一套测试,当然了在理想状态下就会去跑那些测试然后进一步缩小范围。不过书上的大牛的意见是从B=〉A每次都要从头跑一遍,如果有好的服务器当然快了,我的开发机还是算了,分开跑效果还是挺好的。另外也有人说他的方法写了十行,测试写了400行,写测试的时间还不如用来再次思考那个方法。
问题三:可以,所以测试有先后,就像依赖一样;
问题四:差不多,Mock确实给测试带来了很大的帮助,所以一个好的测试环境能事半功倍,比如Nbuilder也是个好帮手。是否可以测试是一个判断代码耦合性的好办法。
问题一:如果是这样的话, 外部因素可能导致失败,A方法 不可测了,单元测试就没必要了?
问题二:你的意思是,要先测试 A方法依赖的B方法,如果B方法有依赖继续先测试里面依赖的方法,A方法最后测?
这样的话,工作量大了
问题三:有顺序? 我看好多测试方法无顺序,删掉也一样,还有救是好多方法都不会去测试,只是用抽象,用Mock去模拟。
问题四:Mock是可以去模拟环境,现在是 我不知道哪些东东需要去模拟,
比如我 认为的 可能导致失败的外部方法需要去模拟,如方法B 要模拟,不知道对不对?
@Qlin:
对待单元测试的时候我觉得最重要的不是看单元测试应该怎么做,而是单元测试是解决什么问题的。
比如我有个api,单元测试作为模拟宿主,在上线前跑一遍而已,这个时候的测试是没有mock的。
有时候我有比较复杂的业务处理的地方,那么我就需要把除业务逻辑外的代码给mock了,保证测试单元的独立和纯净。
我这人比较现实,能解决我问题的我才用,大牛说的话有时候是理论性质的,更多的是指导的意义,所以你说这个单元测试有没有意义或者是不是可以测试,就我的评判标准来说就是能不能解决我的问题。
@今昭:
说的有理
看过大侠的这本书 http://product.china-pub.com/14701 上面的问题你会豁然开朗
另外你举例的是两个public方法,一般的测试是针对public的测试,public方法之间互相调用应该改是设计有些问题
谢谢,呵呵,还没看过这方面的书呢