验证方法被调用并中断执行/忽略以后的失败

时间:2018-06-27 09:50:56

标签: java mockito stubbing

我有一个测试,其中我编写了大部分所需的单元测试,但是有一个我想测试逻辑的前几位。只要方法被调用,我就不会在其余方法中发生什么,但是由于SUT由于缺少进一步的模拟而在NPE上失败,因此测试在我断言之前就失败了。

是否存在调用方法的 clean 方法,并忽略此后发生的所有异常?也许有某种在点击该方法并在此之后中止/通过测试的阻止行为?

我当时以为我可以写when(mock.methodIAmInterestedIn(any)).thenThrow(new RuntimeException("verified!")),然后简单地断言我得到了正确的异常(不过它将包装在另一个异常中)。这可能行得通,但是有点不干净:遮掩了我真正想要测试的内容。

@Test
public void should_load_using_filename_in_config() {
    loader = new OrgUnitLoader(config, dbSupport.mockServices);
    config = mock(TestConfiguration.class);
    /* further mocking of the config needed if I am not to get an NPE */

    when(dao.orgUnitsAreLoaded()).thenReturn(false);

    // call the actual method
    loader.loadOrgUnits();

    verify(config, times(1)).getString(ORG_UNIT_DATA_FILE);
}

例如可以使用CountdownLatch吗?

3 个答案:

答案 0 :(得分:2)

  

我想测试逻辑的前几位。我不在乎其余方法

这似乎是您的受测代码无法通过单一责任模式

您可能会考虑提取该方法的独立部分以将方法分离,甚至更好地分离为自己的对象。结果,您的当前方法将成为使用某些依赖项的组合方法,这些依赖项的逻辑很小,易于测试。


  

有两个明显的缺点:

     
      
  1. 然后,我需要打开SUT,将许多本应该私有的内部方法制作成具有程序包访问权限的方法,以便能够对其进行测试。 – oligofren
  2.   

重点是,有必要独立于填充到当前方法中的实际业务逻辑来验证调度行为。 这告诉我,这种调度行为是它自己的责任,即与其他方法或方法分开。

在我看来,所有其他逻辑都属于其他类,而不仅是同一类中的单独方法。  这是相同抽象级别原则的结果,我们应该将其应用于类以及方法。实际上,这些新类至少将提供package private访问其接口的信息。

  
      
  1. 我将非常紧密地绑定到SUT的内部,但是我想我已经在这样做了– – oligofren
  2.   

这种“紧密绑定”可能仅存在于您的脑中,知道实际的实现。 您需要拆分代码进行测试的事实表明,代码没有您想象的那么严格。

  

我猜想所有单元测试决策(仅测试代码,开放等)都涉及某种实用主义。 –寡糖

关于单元测试,有一个非常简单的规则可以避免所有“务实的决定”:

UnitTest不测试 code ,UnitTest验证公共可观察到的行为,其中 public 表示:返回值与依赖项通信

没有“务实决定”的余地。唯一的决定是: CUT的预期行为是什么

答案 1 :(得分:0)

由于您知道测试加载程序/配置不完整,因此您希望该方法在某些时候失败。在您的测试中考虑它:

@Test
public void should_load_using_filename_in_config() {
    loader = new OrgUnitLoader(config, dbSupport.mockServices);
    config = mock(TestConfiguration.class);
    /* further mocking of the config needed if I am not to get an NPE */

    when(dao.orgUnitsAreLoaded()).thenReturn(false);

    try {
        // call the actual method
        loader.loadOrgUnits();
        Assert.fail("Should fail as config is incomplete.");
    } catch (NullPointerException e) {
        verify(config, times(1)).getString(ORG_UNIT_DATA_FILE);
    }

}

编辑(以下评论)

仅捕获预期的NPE会排除其他异常。如果在调用dao.orgUnitsAreLoaded()之前抛出NPE将会失败。您会注意到的。

也许这不是很复杂,但是很容易理解( KISS )-甚至以后也可以理解。

@see Junit assert something after awaiting and handling an exception

答案 2 :(得分:0)

为什么不使用CompletableFuture,则可以使用no-arg构造函数创建此类的实例来表示将来的某些结果,将其分发给使用者并在将来的某个时间完成使用完整的方法。使用者可以使用get方法来阻止当前线程,直到提供此结果为止。