Mockito/Spy 不工作,正在执行原始功能

Mockito/Spy not working, executing the original function

我有 class :

GP_CategoryService.java 函数 -->

public JSONObject deleteCategory(GP_CategorySubcategoryBean bean) {
        JSONObject data = new JSONObject();
        DirectoryCategoryMaster oCategory = getCategoryMaster(bean);

        if (oCategory.getDirCategoryId() != null) {
            boolean isDeleted = delete(oCategory);
            data.put(ConstantUtil.STATUS, ConstantUtil.SUCCESS);
            data.put(ConstantUtil.DATA, "Category deleted successfully");
        } 
    }

我有 2 个内部函数调用:

  1. getCategoryMaster(bean)
  2. 删除(o类别)

这些基本上是 DAO 调用,直接更新数据库。 现在我想单独模拟这两个函数,这样只要我的测试函数是 运行,它就应该 return 为真。

我的测试函数如下:

@Test
    public void deleteCategoryTestDAOV() {
        JSONObject expected = new JSONObject();
        expected.put(ConstantUtil.STATUS, ConstantUtil.SUCCESS);
        expected.put(ConstantUtil.DATA, "Category deleted successfully");
        
        bean.setCategoryId(1);
        bean.setCategoryName("Test");
        DirectoryCategoryMaster master=new DirectoryCategoryMaster();
        master.setDirCategoryId(1);
        GP_CategoryService mock = spy(new GP_CategoryService());
        when(mock.delete(master)).thenReturn(true);
        when(mock.getCategoryMaster(bean)).thenReturn(master);
        JSONObject actual=new JSONObject();
        actual=mock.deleteCategory(bean);
        assertEquals(expected.toJSONString(), actual.toJSONString());   
    }

但是当我 运行 测试 class 时,它执行实际的功能,mock 不工作。 anhyone 可以帮我解决这个问题吗?

提前致谢!

Mockito 通过在 mock 下创建 class 的 CGLIB 代理来工作。例如,如果您 mock(MyClass.class),您将获得 class MyClass$$EnhancedByMockito$$.class 的动态代理,它扩展了 MyClass.class。由于代理是 MyClass 的子 class,由此产生的 class 允许用户覆盖特定功能(“模拟”它)。通过像 when.

这样易于使用的语句,大部分方法拦截都隐藏在幕后。

遗憾的是,由于 Java 中的限制,无法使用本机反射来代理内部方法调用。这是因为,如果您直接从实例方法 MyClass::a 调用实例方法 MyClass:b,则没有插入代理 class 的间隙,该代理 class 扩展 MyClass 以执行 MyClass::b间接地。

从技术上讲,可以通过一些非常高级的字节码操作(如 ByteBuddy)来做到这一点。

无效示例:

class MyClass {
    public String doSomething() {
        return doSomethingElse();
    }
    
    public String doSomethingElse() {
        return "foo";
    }
}

// ...

class MyTest {

    private MyClass myClass;

    // ...
    @Test
    void myTest() {
        when(myClass.doSomethingElse()).thenReturn("Bar");
        assertEquals("bar", myClass.doSomething()); // FAILS
    }
}

确实有效的示例,使用具有可覆盖方法的中间 class:

class MyClass {

    private MyClassBackend myClassBackend;

    public MyClass(MyClassBackend myClassBackend) {
        this.myClassBackend = myClassBackend;
    }

    public String doSomething() {
        return myClassBackend.doSomethingElse();
    }
}

class MyClassBackend {
    public String doSomethingElse() {
        return "foo";
    }
}

// ...

class MyTest {

    private MyClass myClass;

    @Mock
    private MyClassBackend myClassBackend;

    @BeforeEach
    void setUp() {
        this.myClass = new MyClass(myClassBackend);
    }

    // ...
    @Test
    void myTest() {
        when(myClassBackend.doSomethingElse()).thenReturn("bar");
        assertEquals("bar", myClass.doSomething()); // PASSES
    }
}