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

3

在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;
  }
}

另一个继承自Technology的类是Service

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();
    }

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

请帮我解决这个问题。

提前致谢。


2
你想研究“部分模拟”。或者,也可以使用Mockito的spy功能来实现。 - GhostCat
部分模拟是一种方式。https://static.javadoc.io/org.mockito/mockito-core/2.13.0/org/mockito/Mockito.html#16 - Nkosi
1
请考虑重新设计您的代码。您可能在错误地使用继承,应该使用策略或状态模式(这是单元测试的好处之一-它们促使您改进设计)。仅从继承关系来看:Technology IsA Network. Service IsA Technology. 这听起来正确吗? - user3458
3个回答

0

这应该可以工作。

@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();
  }
}

0
使用spy对象。这里的baseService将成为一个spy。
您可以像对待mock对象一样,在spy对象上添加行为。
我会给你一点头绪-
baseService = Mockito.spy(new BaseService());

顺便说一下,如果你更喜欢组合而非继承,那么你就不会遇到这个问题composition over inheritance


0

正如其他人已经写过的那样,你可以通过间谍来实现这一点,但是我建议你改变测试方法。

在你的非常简单的例子中,所有的null检查都是无关紧要的,因为你总是返回一个恒定的非空值。在这种情况下,没有任何必要进行模拟。

但是考虑到你的基类实际上可能有不同的返回值。你应该编写测试方法,以便通过更改类状态或全局状态(如环境)前提条件来触发替代路径,而不是模拟父类的方法。 通过这种方式,您创建了一个实际情况,在这种情况下,父类行为不同。

这将创建一个更具弹性的测试设置,以应对变化(由于重构)并提供第一形式的集成测试,因为您正在测试专门的类与父类集成的情况。

追求严格隔离的单元测试可能会导致测试套件不能适当地覆盖类之间的协作。严格孤立的测试可能形成自动化测试方法的基础,但是你应该在其上方具有某些程度的集成测试(此处不指与外部服务集成的“真正”的集成测试)。

我的建议是,在明确定义的边界(接口)上仅使用模拟,并尽可能多地使用真实类,并相应地设计您的测试(不要训练模拟,而是准备前提条件)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接