有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用Mockito/PowerMockito来模拟超类的公共方法

在Mockito/PowerMockito中是否仍然存在模拟超类的一些方法

下面是一个场景,它执行多级继承

public class Network {
  public String getNetwork() {
    return "Technology";
  }
}

下面是另一个类Technology,它扩展了Network

public class Technology extends Network {
  public Type getTechnology() {
    String network = getNetwork();
    if(network == null){
      return null;
    }
    return network;
  }
}

另一个类Service扩展了Technology

public class BaseService extends Technology {
  public void getServices() {
    Type type = getTechnology();
    if(type == null){
      throw new Exception('Type not found');
    }
  }
}

我想为BaseService类方法getServices编写一个测试用例,以便在技术类Type为空时引发异常

我试了几步,但还是无能为力

编写的示例测试用例

@Test
    public void test_get_services_should_throw__exception_when_type_is_null() throws Exception{

        //Arrange
        expectedException.expect(Exception.class);

        baseService = Mockito.mock(BaseService.class, Mockito.CALLS_REAL_METHODS);

        when(baseService.getTechnology()).thenReturn(null);


        //Act
        baseService.getServices();
    }

上面的代码片段只是一个示例,可能包含错误。如果有,请忽略

请帮我解决这个问题

提前谢谢


共 (3) 个答案

  1. # 1 楼答案

    使用spy对象。这里baseService可能是个间谍

    您可以在spy对象上添加行为,就像在mock对象上添加行为一样

    我会给你一个小小的开始-

    baseService = Mockito.spy(new BaseService());
    

    顺便说一句,如果你喜欢composition over inheritance,你不会看到这个问题

  2. # 2 楼答案

    正如其他人已经写的,你可以用间谍来做这件事,但我建议你用一种不同的方法来测试

    在您非常简单的示例中,所有的null-检查都是无关的,因为您总是返回一个常量、非空值。在那种特殊情况下,嘲笑是毫无意义的

    但是考虑到基类实际上可能有不同的返回值。您不应该模仿父级的方法,而应该以这种方式编写测试,即通过改变类的“状态”(类状态或全局状态,如环境)先决条件来触发替代路径。 通过这一点,您可以创建一个实际情况,其中父对象的行为不同

    这将创建一个对更改(由于重构)更加健壮的测试设置,并在测试专用类是否集成时进一步提供第一种形式的集成测试 使用父类

    以严格隔离的单元测试为目标可能导致测试套件不能正确地涵盖类之间的协作。严格隔离的测试 MeaE.>构成自动化测试方法的基础,但是您应该在某种程度上进行集成测试(这里不涉及“真正的”集成测试,在这里与外部服务集成)。p>

    我在这里的建议是,仅在定义良好的边界(接口)上使用模拟,并尽可能多地使用真实类,并相应地设计测试(不要训练模拟,而是准备先决条件)

  3. # 3 楼答案

    这应该行得通

    @RunWith(MockitoJUnitRunner.class)
    public class TestInheritance {
    
      @Spy
      BaseService baseService;
    
      @Rule
      public final ExpectedException expectedException = ExpectedException.none();
    
      @Test
      public void test_get_services_should_throw__exception_when_type_is_null() throws Exception{
    
        expectedException.expect(Exception.class);
    
        when(baseService.getTechnology()).thenReturn(null);
    
        baseService.getServices();
      }
    }