1 
                    
                    pudgedoor      2019-02-11 18:56:27 +08:00 via Android    我之前也这么觉得,有一次写单测的时候,set 值弄错了,结果单测断言的时候失败了,然后找到了这个写错的地方。单测应该 mock 数据和 api,测的是业务逻辑吧。我也不太懂,坐等大神解释。 
                 | 
            
     2 
                    
                    momocraft      2019-02-11 19:09:22 +08:00 
                    
                    可以看一下"依赖注入" 
                 | 
            
     3 
                    
                    lhx2008   OP @momocraft 不是注入的问题,是 mock 的问题,dao 层不是固定的,dao 层改了,mock 的对象也得跟着改,这样测试代码和开发代码就完全联动了。 
                 | 
            
     4 
                    
                    earendil1412      2019-02-11 19:28:00 +08:00 via Android    逻辑改了,改单元测试不是很正常吗? 
                 | 
            
     5 
                    
                    CFO      2019-02-11 19:40:09 +08:00 via Android    和我的感觉差不多 我假装在测我假装写的没问题的代码 
                 | 
            
     6 
                    
                    feiyuanqiu      2019-02-11 20:09:35 +08:00    「我如果到时候改成调 dao 类的 getB 方法,测试代码也必须改」 
                应该改。单元测试主要是验证 SUT ( system under test )本身的实现逻辑的正确性,你把实现逻辑都改了,单元测试当然也需要修改。比如你的例子,getA 改成 getB 方法,参数、返回有没有变更?有变更那 service 的代码就需要修改,service 修改了就需要单元测试确保修改的正确性;如果只是换个名字,现在 IDE 的重构功能可以把相关名称都替换了,也不需要手动修改。 「但是 mockito 这种测试代码和实际代码强耦合的情况,我必须把被测代码的所有其他类调用都找出来并且 mock 」 mock 是个测试替身,你不告诉它在被调用时应该怎么返回,它也不清楚你究竟想要什么。如果你不需要 mockito 的灵活性,完全可以为这个类写一个替身实现,然后在测试中使用这个替身类,就不需要在每个依赖这个类的地方都写一遍 mockito 代码了。 「写测试的时候,我假设我原来的代码没问题,才找调用出来 mock,而测出来肯定也没有问题呀」 mockito 主要还是在 TDD 中用得多些,你在写代码的时候,依赖类还没实现,这时候就需要用测试替身来完成单元测试。依靠 mockito 的灵活性,方便调整依赖类的入参返回,等上层实现稳定后,也就相当于依赖类的实现契约也建立好了,就可以根据这个契约再去实现依赖类...以此类推。如果是先写代码,再写测试,确实会有你这种感觉。  | 
            
     7 
                    
                    feiyuanqiu      2019-02-11 20:16:55 +08:00    再补充一些,《 Practical Unit Testing with JUnit and Mockito 》这本书讲得比较细,可以看一看。 
                 | 
            
     8 
                    
                    lhx2008   OP @feiyuanqiu 谢谢,很客观,用 TDD 的思路来说是讲得通的,但是真的完全使用这一套方法似乎工作量会陡增。如果不是 TDD,我认为还是只有在数据源确实还没有时(如别人写的接口)用 mock 的比较合适,全部 mock (包括自己写的 dao 等) 似乎不太现实。当然完全 TDD 也是有很多内容,我也不是很了解。 
                 | 
            
     9 
                    
                    kaneg      2019-02-11 20:43:56 +08:00 via iPhone    mock 将本来不可测的代码变成可测的,降低了系统的不确定性,这本来就已经很了不起了,还要啥自行车。 
                 | 
            
     10 
                    
                    ipwx      2019-02-11 21:08:35 +08:00    你的问题用任何测试工具本身都是解决不了的。 
                你得换编程模型。 比如 Actor Model (代表类库 Scala Akka ),就基本没有 Mock 的问题。 缺点是学习曲线比较抖。  | 
            
     11 
                    
                    DeweyReed      2019-02-11 21:14:44 +08:00 
                    
                    图个安心..(狗头 
                 | 
            
     12 
                    
                    richard1122      2019-02-12 00:06:52 +08:00    "写测试的时候,我假设我原来的代码没问题,才找调用出来 mock,而测出来肯定也没有问题呀。而事实上,问题很多时候就是出在别的类调用的实际返回值不符合预期。" 
                如果有些非常简单的业务逻辑可能不适合这类单元测试的,也有可能是业务逻辑没有抽象好,分散在各处。 如果能比较好的把业务逻辑“内聚”了,方便测某一部分  | 
            
     13 
                    
                    richard1122      2019-02-12 00:08:33 +08:00    从另一个角度来说楼主大概追求的是集成测试?比如测某个接口前直接把 DB 数据准备好,然后传一些参数,里面真实跑,然后直接看返回值或者结束后 DB 状态。 
                我觉得也不用过度追求单元测试,某些情况下单元测试好用,某些情况下也可以直接上集成测试  | 
            
     14 
                    
                    hlwjia   PRO 推荐阅读的 Write tests. Not too many. Mostly integration. 
                 | 
            
     15 
                    
                    aijam      2019-02-12 04:53:41 +08:00 
                    
                    TDD 和 Restful 什么的都一样,都是鸡汤玄学。 
                 | 
            
     16 
                    
                    lzdhlsc      2019-02-12 05:42:23 +08:00    接口和模块化的意义不就在于此吗?当你写一个单元测试的时候,你不关心 dependency 的逻辑实现,你只关心接口。至于 dependency 如何测试,在你的测试中不应该关心。 
                 | 
            
     17 
                    
                    lhx2008   OP @lzdhlsc  
                是这样子,我的重点是我还要用 mock 模拟并跟踪 dependency 的行为,是巨大的负担。 一些 dependency 由于被封装不彻底,他的所有行为你甚至无法掌握,比如 redis 客户端,http 接口调用等。报错处理,或者执行反馈你都必须要 mock 到。工作量巨大,而且没 mock 到还很麻烦。 一些 dependency 没有设计好,后面改了行为,但是这个时候如果 mock 没有跟着改,又会出现类似的问题。 如果不用 mock 直接测的话,我则只需要被测对象关心本身的行为,我不需要关心 dependency,换了 dependency 也和这个测试没关系。  | 
            
     18 
                    
                    q4336431      2019-02-12 09:47:10 +08:00 
                    
                    我用 Mockito 就是为了省去从数据库或者缓存里面拿数据源的操作步骤 
                 | 
            
     19 
                    
                    lzdhlsc      2019-02-12 11:46:51 +08:00 
                    
                    @lhx2008 有道理。有时候确实直接用 dependency 比较好, 我能想到的无法替代 mock 的场景就是 error handling 了,毕竟模拟某些 java driver throw exception 有时候很难。另外有时候有些 test driver 很好用 比如 mock mongo 的 Fongo。 
                 | 
            
     20 
                    
                    loveCoding      2019-02-12 11:52:17 +08:00 
                    
                    需求变动,改单测是免不了的,楼主可以试试 tdd 
                先写单测,等到场景覆盖完了单测也就写完了,业务实现空方法,剩下的就是实现逻辑而已.  |