为不太可能的情况创建单元测试,是否值得这样做?

时间:2019-01-11 15:11:06

标签: java unit-testing

对于下面的方法,是否有一种方法可以创建导致DatatypeConfigurationException的单元测试,因此我可以测试它是否抛出了ConversionException

这是我的代码:

public static XMLGregorianCalendar getXMLGregorianCalendar(final LocalDate localDate) {
    XMLGregorianCalendar xmlGregorianCalendar = null;
    if (localDate != null) {
        final String dateString = localDate.format(yyyMMddFormat);
        try {
            xmlGregorianCalendar = DatatypeFactory.newInstance().newXMLGregorianCalendar(dateString);
        } catch (DatatypeConfigurationException e) {
            throw new ConversionException("Unable to format LocalDate.", e);
        }
    }

    return xmlGregorianCalendar;
}

4 个答案:

答案 0 :(得分:2)

您可以通过设置要实例化的类名的系统属性来覆盖工厂将创建的实现。然后,该类可以在该方法中引发异常。

例如这样的

public class FailingDatatypeFactory implements DatatypeFactory {
   public XMLGregorianCalendar newXMLGregorianCalendar() { throw new DatatypeConfigurationException() }
}

然后像这样设置

System.setProperty("javax.xml.datatype.DatatypeFactory", FailingDatatypeFactory.class.getName());

现在,在运行测试用例之后,您应该清除属性,以便其他测试都无法尝试实例化该实现。

答案 1 :(得分:1)

您可以:

  1. 例如,使用PowerMock模拟静态方法(DatatypeFactory.newInstance()),并将其设置为引发DatatypeConfigurationException。然后在单元测试中,检查此异常是否被ConversionException包装。

  2. 因为我不喜欢模拟静态方法,所以我会创建一个新组件-例如XmlGregorianCalendarProvider(它将在内部使用DatatypeFactory.newInstance()。newXMLGregorianCalendar(dateString)),并使用标准模拟对其进行模拟机制(例如JUnit)。 仍然在单元测试中,检查此异常是否被ConversionException包装。

答案 2 :(得分:1)

这里, <rewrite> <rules> <clear /> <rule name="Redirect Angular endpoints to MVC Home" enabled="true"> <match url="^(profiel|timesheets|facturen|opdrachten|contact|help|gebruikers)" negate="false" /> <conditions logicalGrouping="MatchAll" trackAllCaptures="false" /> <action type="Rewrite" url="Home" logRewrittenUrl="false" /> </rule> <!-- Some other rules that are not important are here, they redirect HTTP to HTTPS --> </rules> </rewrite> 引发了检查的异常。
这是一种静态方法。因此,您不能直接嘲笑它。

1)作为替代,您可以尝试找到可能引发异常的情况。
我们走吧。例外是在这里抛出:

javax.xml.datatype.DatatypeFactory.newInstance()

因此,当private static <T> T findServiceProvider(final Class<T> type) throws DatatypeConfigurationException{ try { return AccessController.doPrivileged(new PrivilegedAction<T>() { public T run() { final ServiceLoader<T> serviceLoader = ServiceLoader.load(type); final Iterator<T> iterator = serviceLoader.iterator(); if (iterator.hasNext()) { return iterator.next(); } else { return null; } } }); } catch(ServiceConfigurationError e) { final DatatypeConfigurationException error = new DatatypeConfigurationException( "Provider for " + type + " cannot be found", e); throw error; } } 被抛出并被捕获时,DatatypeConfigurationException被抛出。但是ServiceConfigurationError是错误而不是例外。
试图模拟错误变得非常棘手。

2)测试它的另一种方法:将ServiceConfigurationError包装在您自己的类的实例中。
这样,您可以轻松模拟它:

DatatypeFactory.newInstance()

现在以这种方式更改代码:

public class DataTypeFactoryWrapper { 
   public DatatypeFactory newInstance(){
      return DatatypeFactory.newInstance();
   }
}

现在,您可以在测试类中模拟private DataTypeFactoryWrapper dataTypeFactoryWrapper; //... xmlGregorianCalendar = dataTypeFactoryWrapper.newInstance().newXMLGregorianCalendar(dateString);

3)最后一种选择:不要测试。照原样考虑,这是一个dataTypeFactoryWrapper包装器,而Error很难测试。
不论javadoc解释什么:

  

错误是Throwable的子类,指示严重问题   合理的应用程序不应试图抓住。大多数这样   错误是异常情况

答案 3 :(得分:1)

对于单元测试,我只需要这样做。您需要做的只是将Sys属性javax.xml.datatype.DatatypeFactory设置为无效值。当它试图找到不存在的类时,它将抛出异常。测试结束后,请务必清除道具。