1
pudgedoor 2019-02-11 18:56:27 +08:00 via Android 1
我之前也这么觉得,有一次写单测的时候,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 3
逻辑改了,改单元测试不是很正常吗?
|
5
CFO 2019-02-11 19:40:09 +08:00 via Android 1
和我的感觉差不多 我假装在测我假装写的没问题的代码
|
6
feiyuanqiu 2019-02-11 20:09:35 +08:00 2
「我如果到时候改成调 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 2
再补充一些,《 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 1
mock 将本来不可测的代码变成可测的,降低了系统的不确定性,这本来就已经很了不起了,还要啥自行车。
|
10
ipwx 2019-02-11 21:08:35 +08:00 1
你的问题用任何测试工具本身都是解决不了的。
你得换编程模型。 比如 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 1
"写测试的时候,我假设我原来的代码没问题,才找调用出来 mock,而测出来肯定也没有问题呀。而事实上,问题很多时候就是出在别的类调用的实际返回值不符合预期。"
如果有些非常简单的业务逻辑可能不适合这类单元测试的,也有可能是业务逻辑没有抽象好,分散在各处。 如果能比较好的把业务逻辑“内聚”了,方便测某一部分 |
13
richard1122 2019-02-12 00:08:33 +08:00 1
从另一个角度来说楼主大概追求的是集成测试?比如测某个接口前直接把 DB 数据准备好,然后传一些参数,里面真实跑,然后直接看返回值或者结束后 DB 状态。
我觉得也不用过度追求单元测试,某些情况下单元测试好用,某些情况下也可以直接上集成测试 |
14
hlwjia 2019-02-12 01:46:03 +08:00 via iPhone 2
推荐阅读的 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 1
接口和模块化的意义不就在于此吗?当你写一个单元测试的时候,你不关心 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
先写单测,等到场景覆盖完了单测也就写完了,业务实现空方法,剩下的就是实现逻辑而已. |