Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 方法不会抛出JUnit5测试用例_Java_Log4j_Tdd_Junit5_Assertion - Fatal编程技术网

Java 方法不会抛出JUnit5测试用例

Java 方法不会抛出JUnit5测试用例,java,log4j,tdd,junit5,assertion,Java,Log4j,Tdd,Junit5,Assertion,我有一个定制的Log4j appender,它作为一个单例类实现,在调用类的getInstance()方法时需要一个布局对象。 我编写了一个JUnit5测试用例来测试在未设置布局对象时是否引发异常。如果没有设置布局,我抛出了一个IllegalArgumentException 下面的代码在执行时引发异常 public class App { public static void main(String[] args){ Logger logger = Logger.get

我有一个定制的Log4j appender,它作为一个单例类实现,在调用类的
getInstance()
方法时需要一个布局对象。 我编写了一个JUnit5测试用例来测试在未设置布局对象时是否引发异常。如果没有设置布局,我抛出了一个
IllegalArgumentException

下面的代码在执行时引发异常

public class App {
    public static void main(String[] args){
        Logger logger = Logger.getLogger("test");

        CustomAppender m = CustomAppender.getInstance();
        logger.addAppender(m);

        logger.info("test"); // Exception is thrown by this statement
    }
}
但是,下面的测试用例失败。事实上,没有抛出异常

@Test
public void testException(){
    Logger logger = Logger.getLogger("test");

    CustomAppender m = CustomAppender.getInstance();
    logger.addAppender(m);

    assertThrows(Exception.class, () -> {
        logger.info("test");
    });
}
我错过了什么

编辑:来自
CustomAppender
类的更多代码

private CustomAppender(Layout layout, ArrayList<LoggingEvent> list) {
    cLayout = layout;
    eventsList = list;
    discardedLogCount = 0;

    super.setLayout(cLayout);
}

// Instance with a user-defined list and a layout
public static CustomAppender getInstance(Layout layout, ArrayList<LoggingEvent> list) {
    if (INSTANCE == null) {
        // Thread-safety
        synchronized (CustomAppender.class) {
            INSTANCE = new CustomAppender(layout, list);
        }
    }
    return INSTANCE;
}

// Instance with an empty list
public static CustomAppender getInstance(Layout layout){
    return CustomAppender.getInstance(layout, new ArrayList<>());
}

// Instance with a null layout
public static CustomAppender getInstance(ArrayList<LoggingEvent> list){
    return CustomAppender.getInstance(null, list);
}

// Default instance
public static CustomAppender getInstance(){
    return CustomAppender.getInstance(null, new ArrayList<>());
}

// Appends at most maxSize items
@Override
protected void append(LoggingEvent event) throws IllegalArgumentException {
    if (this.cLayout == null)
        throw new IllegalArgumentException();

    if (eventsList.size() < maxSize) {
        eventsList.add(event);
    } else {
        // Remove the oldest item and add a new one
        eventsList.remove(0);
        discardedLogCount++;
        eventsList.add(event);
    }
}
private CustomAppender(布局、阵列列表){
cLayout=布局;
事件列表=列表;
discardedLogCount=0;
超级设置布局(cLayout);
}
//具有用户定义的列表和布局的实例
公共静态CustomAppender getInstance(布局、ArrayList列表){
if(实例==null){
//线程安全
已同步(CustomAppender.class){
实例=新的CustomAppender(布局、列表);
}
}
返回实例;
}
//具有空列表的实例
公共静态CustomAppender getInstance(布局){
返回CustomAppender.getInstance(布局,新ArrayList());
}
//具有空布局的实例
公共静态CustomAppender getInstance(ArrayList列表){
返回CustomAppender.getInstance(null,list);
}
//默认实例
公共静态CustomAppender getInstance(){
返回CustomAppender.getInstance(null,new ArrayList());
}
//最多追加maxSize项
@凌驾
受保护的void append(LoggingEvent事件)引发IllegalArgumentException{
如果(this.cLayout==null)
抛出新的IllegalArgumentException();
if(eventsList.size()
如果未传递
Layout
参数,是否从
CustomAppender.getInstance()
抛出
IllegalArgumentException
?或者你要等到调用了
Logger.info()
之后再开始吗?不,我知道这是违反直觉的,但这是作业中要求的。相反,我在重载的
append()
方法中执行先决条件检查,该方法在执行
Logger.info()
时调用。我使用了一个调试器并验证了我的前提条件检查(即,如果我的私有布局对象为null,则抛出一个异常)工作正常,但由于某种原因测试失败。事实上,如果我对
assertThrow()
调用进行注释,并且只执行
logger.info()
,它就可以正常工作。它会按预期抛出
异常
?它不会失败,因为您的测试没有被隔离。如果您已经在
CustomAppender
上至少调用了一次
getInstance
,并给它一些
Layout
,那么从那时起,您将获得该布局的实例。由于
INSTANCE
字段是静态的,所以该行为会一直持续到类加载器垃圾回收为止,对于您的测试来说,这可能是“永远的”。您应该以某种方式显式地创建所需的appender,而不是依赖于您的测试第一个调用该方法。如果您的实例实际上是用外部的东西参数化的,因此不是一个单例,而是一个
Layout->Appender
的缓存工厂,那么为什么要遵循单例模式呢?如果您希望通过调用代码将其视为单例,但在启动时仍为配置打开,则必须拆分关注点,并且不要让
getInstance()
也初始化单例。还有另一种方法,比如
init(Layout,List)
,这样您也可以在测试中使用
init
方法,甚至在测试后进行清理。