Mockito创建的Mock调用Getter时未用构造函数值,原因何在?
问题原因及解决办法
为什么Mock对象的getPrice()不返回18.99?
Mockito用@Mock创建的是完全模拟的代理对象,它不会执行原Football类的任何构造逻辑,也不会保留原类的字段和方法实现:
- 原类构造函数里硬编码的
18.99是传给父类的,但Mock对象根本不会调用这个构造方法; getPrice()方法在Mock对象里被替换成了Mockito的默认实现,对于Double类型的返回值,默认返回null,自然不会得到你想要的18.99。
另外提一句:你原Football类的逻辑有个小矛盾——构造函数给父类传的是18.99,但自己的getPrice()返回的是构造参数里的price,这俩本来就不是同一个值,就算用真实对象,getPrice()也不会返回18.99,而是返回你构造时传入的price参数。
怎么解决?
根据你的测试需求选对应的方式:
1. 直接创建真实对象(测试POJO自身逻辑用)
如果你的测试就是要验证Football的自身逻辑,完全没必要用Mock,直接new实例就行:
Football football = new Football(Colour.RED, 20.0); // 此时getPrice()返回的是传入的20.0,父类的价格是18.99
2. 用@Spy做部分模拟(需要保留原类部分方法逻辑)
如果你需要模拟Football的某些方法,但想保留getPrice()的原逻辑,用@Spy代替@Mock,而且必须显式调用构造函数初始化:
@Spy Football football = new Football(Colour.BLUE, 15.0); @BeforeEach private void initMocks() { MockitoAnnotations.openMocks(this); }
这时调用getPrice()会执行原方法,返回构造时传入的15.0。
3. 给Mock对象指定返回值(必须用Mock的情况)
如果一定要用@Mock,可以通过Mockito指定getPrice()的返回值:
@Mock Football football; @BeforeEach private void initMocks() { MockitoAnnotations.openMocks(this); when(football.getPrice()).thenReturn(18.99); }
这样调用football.getPrice()就会返回你期望的18.99。
内容的提问来源于stack exchange,提问作者java12399900
相关产品推荐
相关产品推荐

