V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
gzk329
V2EX  ›  Java

请教一个 Mock 单元测试问题?

  •  
  •   gzk329 · 2022-09-10 13:27:28 +08:00 · 2104 次点击
    这是一个创建于 806 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如图所示,一个测试类中,有一个 @InjectMock 桩点 桩点依赖一个 bean 需要真实方法 所以打了 @Spy 注解,那么这个 bean 的依赖该怎么表示?我需要 @Mock --->>> 注入 bean ---->>> 注入 桩点

    11 条回复    2022-09-14 21:36:55 +08:00
    JasonLaw
        1
    JasonLaw  
       2022-09-10 15:08:54 +08:00
    首先我会有一些疑问,为什么你一定要 @Spy ?为什么你需要这个依赖的真实行为?
    JasonLaw
        2
    JasonLaw  
       2022-09-10 15:19:10 +08:00
    如果你只是想要达成这样的行为,多级依赖注入,你可以看一下 https://stackoverflow.com/questions/6300439/multiple-levels-of-mock-and-injectmocks

    不过还是那句话,不建议这么做,当你这么做的时候,不然你的代码有问题,不然你的单元测试有问题。
    chihiro2014
        4
    chihiro2014  
       2022-09-10 15:28:37 +08:00
    一般不需要 spy ,能 mock 的都能 mock 出来,如果是私有方法,那通常也是走公有方法的逻辑,调用私有。有参构造的 mock 我觉得 mock 不来
    chihiro2014
        5
    chihiro2014  
       2022-09-11 23:39:55 +08:00
    来更新下,刚好这两天单元测试,又写到了无法吐槽的地方,于是一激灵,就用了楼主说的 spy ,大概场景是 Resttemplate 部分需要设置权限相关的一些参数。我们这边代码比较古早,resttemplate 直接 new 出来,而不是 autowired ,不得不感叹,代码写的烂,mock 都 mock 不动。。。
    chihiro2014
        6
    chihiro2014  
       2022-09-11 23:46:40 +08:00
    感谢下楼主给的经验,这里来表示下我的看法。
    正常情况下,我们写单元测试,以 Spring 为例,配合 Junit 和 Mockito 。
    假设测试类为 A ,他里面依赖了 Service B 、
    那么正常的写法通常就是
    ···code
    @ExtendsWith(xxxx)
    public class ATest {
    @InjectMock
    A a;

    @Mock
    B b;

    @Test
    public void testMethod() {}

    ```
    这种情况往往是代码封装的很好(相对来说),所以任意 mock B 提供的返回值。

    奇葩情况就是你说的 spy ,需要多层 mock ,那这个时候你就得去查看 B 中用到的依赖,全部 Mock 。
    这种就属于 mock 的程度比较深。也建议检查下代码是否有问题。最近就是被这个所干扰了
    zhazi
        7
    zhazi  
       2022-09-13 10:42:19 +08:00
    @JasonLaw
    我理解无返回值的测试对象都需要使用 spy 预测对象行为
    UserService spyUserService = spy(new UserService(mock(UserDao.class)));
    spyUserService.saveUser();
    verify(spyUserService,times(1)).saveLog();
    JasonLaw
        8
    JasonLaw  
       2022-09-13 11:08:44 +08:00
    @zhazi #7 如果你要测试的是 UserService 的话,我觉得应该是使用 @InjectMocks ,而不是 @Spy

    具体可以看一下 https://stackoverflow.com/questions/38567326/is-it-discouraged-to-use-spy-and-injectmocks-on-the-same-field

    重点是:@Spy and @Mock are meant for dependencies, and not for the functionality you are testing
    gzk329
        9
    gzk329  
    OP
       2022-09-14 21:24:54 +08:00
    @JasonLaw 你好 其实我的业务场景是 一个 Class A 测试类 @InjectMock 中有一个文件上传下载工具类 我测试需要这个工具类使用他自己真实的方法 所以我就对其使用了 @Spy 这个工具类中又有依赖的类 我也需要对这些类使用 mock 模拟数据
    我现在的解决方案是 @Resource 和 @InjectMock 一起使用了 既直接注入了测试类对象 同时 又能 mock 其中的一些依赖
    gzk329
        10
    gzk329  
    OP
       2022-09-14 21:26:33 +08:00   ❤️ 1
    @chihiro2014 我的场景是三层的 我现在是使用 @Resource 和 @InjectMock 一起使用 可以达到我要的效果 供参考
    chihiro2014
        11
    chihiro2014  
       2022-09-14 21:36:55 +08:00
    @gzk329 遇上这种需要文件 io 的操作,其实特别不好 mock
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4029 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 05:15 · PVG 13:15 · LAX 21:15 · JFK 00:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.