如何对调用给定方法的任何对象进行抑制/执行任何操作?

How to suppress/doNothing for any object calling a given method?

提问人:user1255276 提问时间:11/18/2023 最后编辑:user1255276 更新时间:11/20/2023 访问量:74

问:

Class ClassA
{

  DatabaseObject dba

  public classA(DatabaseObject db) { dba = db}

  Method methodA(String stringA)
  {

    DatabaseEntityA objectA = new DatabaseEntityA();

    objectA.save(stringA);

  }
}
class testClass
{

  @InjectMocks
  DatabaseObject mockDB = mock(DatabaseObject.class);


  void testMethod()
  {

    ClassA classA = new ClassA(mockDB);

    //How to mock objectA.save to do nothing!
    //PowerMockito.suppress(PowerMockito.method(DatabaseEntityA.class "save")); ?? this doesn't work
    //doNothing.when(ArgumentMatchers.any(DatabaseEntityA.class)).save() // does not work, throws a exception
    classA.methodA("mock data");
  }
}

我不明白如何在不更改对该对象的访问的情况下创建 objectA 的模拟对象,我不想这样做。那么我怎样才能使 mockito 只是抑制对 DatabaseEntityA 类型的任何对象的 save 方法的任何调用?

编辑:答案:归功于:knittl

基本上,这是做不到的。给一个阅读抛出给出的答案链接。

无法通过新调用模拟在方法中创建的对象。如果您有一个使用 new 创建的对象,并且需要模拟它,则需要重构该对象,以便它不会使用 new 调用创建。 如果它是由其他方式创建的,则需要模拟该对象的创建方式,然后将其分配给该对象。

即。

DatabaseEntityA objectA = new DatabaseEntityA(); //can not be mocked

将其更改为如下所示:

//in the class
DatabaseEntityA objectA = getNewObjectA();
//the test
void testMethod()
{
  ClassA classA = new ClassA(mockDB);
  DatabaseEntityA mockedEntityA = mock(DatabaseEntityA.class);
  
  doReturn(mockedEntityA).when(classA).getNewObjectA();  
  doNothing().when(mockedObjectA).save();
  //Or if you save is not a void
  //doReturn(null).when(mockedObjectA).save();

  classA.methodA("mock data");

}
java 单元测试 mockito powermock powermockito

评论

0赞 daniu 11/18/2023
为什么要禁止调用?它正在调用模拟,您要检查调用是否已执行。
0赞 user1255276 11/18/2023
因为我需要,这显然只是一个示例代码,
1赞 Old Dog Programmer 11/18/2023
如果你的问题中要有示例代码,即使是为了说明一个假设,它也应该是能够干净编译的代码。
1赞 Andrew S 11/18/2023
看起来像是这个的副本。
1赞 knittl 11/18/2023
为什么在执行单元测试时没有调用我的模拟方法?– 您无法(轻松)测试在方法中创建的对象。一些注意事项:从未被您的类使用过,为什么它是依赖项?不得混合和手动分配。DatabaseObject@InjectMocks

答:

0赞 user1255276 11/20/2023 #1

:归功于:knittl

基本上,这是做不到的。给一个阅读抛出给出的答案链接。

顶级域名:

无法通过新调用模拟在方法中创建的对象。如果您有一个使用 new 创建的对象,并且需要模拟它,则需要重构该对象,以便它不会使用 new 调用创建。如果它是由其他方式创建的,则需要模拟该对象的创建方式,然后将其分配给该对象。

即。

DatabaseEntityA objectA = new DatabaseEntityA(); //can not be mocked

将其更改为如下所示:

//in the class
DatabaseEntityA objectA = getNewObjectA();

是的,你的方法可以是这样的,但它需要是公共的

public DatabaseEntityA getNewObjectA()
{
return new DatabaseEntityA();
}
//the test
void testMethod()
{
  ClassA classA = new ClassA(mockDB);
  DatabaseEntityA mockedEntityA = mock(DatabaseEntityA.class);
  
  doReturn(mockedEntityA).when(classA).getNewObjectA();  
  doNothing().when(mockedObjectA).save();
  //Or if you save is not a void
  //doReturn(null).when(mockedObjectA).save();

  classA.methodA("mock data");

}