alibaba / testable-mock

换种思路写Mock,让单元测试更简单
https://alibaba.github.io/testable-mock/
MIT License
1.83k stars 310 forks source link

Mock似乎只能关联两个服务 #277

Closed hello-fk closed 2 years ago

hello-fk commented 2 years ago

情况一:三个服务,serviceA,serviceB,serviceC,serviceA.methodA调用了serviceB.methodB,serviceB.methodeB调用了serviceC.methodC,测试类是serviceATest,关联了一个Mock,Mock中mock了methodC,但是在我实际跑的过程中,从methodA进入,对methodC不生效,如果是mock了methodB,则生效

情况二:两个服务,serviceA,serviceB,serviceA.methodA调用了serviceA.methodA1,serviceA.methodA1调用了serviceB.methodB,测试类是serviceATest,关联了一个Mock,Mock中mock了methodB,在我实际跑的过程中,从methodA进入,对methodB生效,如果mock了mthodA1,对mthodA1也生效

同样是三次调用,但是结果不一样,是因为情况一跨了三个服务,而情况二只跨了两个服务吗

linfan commented 2 years ago

TestableMock的Mock是作用在 方法调用 上,而不是 方法定义 上,在跨类型调用的时候,需要将Mock类关联在实际发起调用的类上。

情况1: serviceA.methodA -> serviceB.methodeB -> serviceC.methodC

这时候调用serviceC.methodC的代码是在ServiceB类里,虽然发起测试的是ServiceA的测试用例,但Mock方法需要定义在ServiceBMock类(或ServiceBTest.Mock类)才能在运行期间自动替换对serviceC.methodC调用的。

在跨类型的单元测试中使用TestableMock会让测试和Mock分开写到两个类型里,确实会有一些不符合直觉。

情况2: serviceA.methodA -> serviceA.methodA1 -> serviceB.methodeB

这种情况要测试的类和发起serviceB.methodeB调用的类都是ServiceA,因此Mock定义写在ServiceATest.Mock就会生效。

JYHarvest commented 2 years ago

请问,是ServiceBTest.Mock还是ServiceBImplTest.Mock

linfan commented 2 years ago

ServiceATest.MockServiceAMock,包含调用的业务类+Test.Mock 或 包含调用的业务类+Mock

JYHarvest commented 2 years ago

@MockInvoke的targetClass为啥指向的是接口类?而不是实现类?

linfan commented 2 years ago

@JYHarvest 在FAQ文档里有提到,targetClass始终和业务类调用目标方法时候,使用的那个对象类型保持一致。

文档中提到"Mock方法的首个参数",这个是早期版本的用法,现在版本应该是targetClass参数,这个问题我也抽空更新一下文档。

举例来说,比如定义了一个ServiceA接口类型的变量,并初始化为ServiceAImpl类型对象。

private ServiceA svc = new ServiceAImpl();

希望Mock掉代码里此对象的biz()调用

svc.biz()

targetClass应当指向svc对象定义的类型,即ServiceA

JYHarvest commented 2 years ago

3q 我已经在用了

 

------------------ 原始邮件 ------------------ 发件人: "alibaba/testable-mock" @.>; 发送时间: 2022年6月9日(星期四) 下午4:33 @.>; @.**@.>; 主题: Re: [alibaba/testable-mock] Mock似乎只能关联两个服务 (Issue #277)

在FAQ文档里有提到,targetClass始终和业务类调用目标方法时候,使用的那个对象类型保持一致。

文档中提到"Mock方法的首个参数",这个是早期版本的用法,现在版本应该是targetClass参数,这个问题我也抽空更新一下文档。

举例来说,比如定义了一个ServiceA接口类型的变量,并初始化为ServiceAImpl类型对象。 private ServiceA svc = new ServiceAImpl();

希望Mock掉代码里此对象的biz()调用 svc.biz()

则targetClass应当指向svc对象定义的类型,即ServiceA。

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>

linfan commented 2 years ago

ok,相应文档已更新