为什么每个后续日志条目都会重复(使用java.util.logging)?

为什么每个后续日志条目都会重复(使用java.util.logging)?,java,java.util.logging,Java,Java.util.logging,我有一个测试,我想记录一些测试信息。我使用基本java logger成功地做到了这一点,但我做错了什么。每个后续条目日志消息都会成倍增加,即第一条消息记录一次,第二条消息记录两次,第三条消息记录三次,等等。我不确定我做错了什么。消息也被推送到控制台,但只有一次 public class MyExampleTest { private FileHandler fh = null; private static final Logger logger = Logger.getLogg

我有一个测试,我想记录一些测试信息。我使用基本java logger成功地做到了这一点,但我做错了什么。每个后续条目日志消息都会成倍增加,即第一条消息记录一次,第二条消息记录两次,第三条消息记录三次,等等。我不确定我做错了什么。消息也被推送到控制台,但只有一次

public class MyExampleTest {
    private FileHandler fh = null;
    private static final Logger logger = Logger.getLogger(MyExampleTest.class.getName());
    SimpleFormatter formatter = new SimpleFormatter();

    @Test
    public void infoPackage() throws Exception {
        fh = new FileHandler("test.log", true);
        // do some test stuff
        writeEntryToLogFile("entry one");
        // do some more test stuff
        writeEntryToLogFile("entry two");
        // do even more test stuff
        writeEntryToLogFile("entry three");
    }

    private void writeEntryToLogFile(String message) throws Exception {
        fh.setFormatter(formatter); 
        logger.addHandler(fh);
        logger.info(message);
    }

}
我的日志文件的结尾如下:

entry one
entry two
entry two
entry three
entry three
entry three

我想我把文件处理程序搞乱了,但我不知道是什么。

尝试在
infoPackage()方法中的语句下方移动

fh.setFormatter(格式化程序);
记录器.addHandler(fh)


由于方法调用,这些语句被多次设置。

请尝试在
infoPackage()方法中的语句下方移动

fh.setFormatter(格式化程序);
记录器.addHandler(fh)


由于方法调用的缘故,它们被多次设置。

每次添加消息时,您都在添加相同的处理程序。你应该只做一次。我建议使用静态初始化器

我已经注释掉了您不再需要的行:

public class MyExampleTest {
    //private FileHandler fh = null;
    private static final Logger logger;
    //SimpleFormatter formatter = new SimpleFormatter();

    static {
        logger = Logger.getLogger(MyExampleTest.class.getName());
        FileHandler fh = new FileHandler("test.log", true);
        fh.setFormatter(new SimpleFormatter());
        logger.addHandler(fh);
    }

    @Test
    public void infoPackage() throws Exception {
        //fh = new FileHandler("test.log", true);
        // do some test stuff
        writeEntryToLogFile("entry one");
        // do some more test stuff
        writeEntryToLogFile("entry two");
        // do even more test stuff
        writeEntryToLogFile("entry three");
    }

    private void writeEntryToLogFile(String message) throws Exception {
        //fh.setFormatter(formatter); 
        //logger.addHandler(fh);
        logger.info(message);
    }
}

值得注意的是,
writeEntryToLogFile
现在有点毫无意义,因为它只是一行。我会去掉这个函数。

每次添加消息时,都会添加相同的处理程序。你应该只做一次。我建议使用静态初始化器

我已经注释掉了您不再需要的行:

public class MyExampleTest {
    //private FileHandler fh = null;
    private static final Logger logger;
    //SimpleFormatter formatter = new SimpleFormatter();

    static {
        logger = Logger.getLogger(MyExampleTest.class.getName());
        FileHandler fh = new FileHandler("test.log", true);
        fh.setFormatter(new SimpleFormatter());
        logger.addHandler(fh);
    }

    @Test
    public void infoPackage() throws Exception {
        //fh = new FileHandler("test.log", true);
        // do some test stuff
        writeEntryToLogFile("entry one");
        // do some more test stuff
        writeEntryToLogFile("entry two");
        // do even more test stuff
        writeEntryToLogFile("entry three");
    }

    private void writeEntryToLogFile(String message) throws Exception {
        //fh.setFormatter(formatter); 
        //logger.addHandler(fh);
        logger.info(message);
    }
}

值得注意的是,
writeEntryToLogFile
现在有点毫无意义,因为它只是一行。我会去掉这个函数。

每次调用
writeEntryToLogFile()
时都会添加一个处理程序
因此,每次调用时都会有额外的重复输出

您应该添加一个设置方法,在其中为每个执行的测试设置上下文
您正在使用的JUnit允许它与
@Before
注释一起使用:

@Before
public void setup() {
    fh = new FileHandler("test.log", true);
    formatter = new SimpleFormatter();
    fh.setFormatter(formatter); 
    logger.addHandler(fh);
}

另一方面,断言没有任何东西的测试方法没有真正的意义。

每次调用
writeEntryToLogFile()
时,都会添加一个处理程序
因此,每次调用时都会有额外的重复输出

您应该添加一个设置方法,在其中为每个执行的测试设置上下文
您正在使用的JUnit允许它与
@Before
注释一起使用:

@Before
public void setup() {
    fh = new FileHandler("test.log", true);
    formatter = new SimpleFormatter();
    fh.setFormatter(formatter); 
    logger.addHandler(fh);
}

作为旁注,断言没有任何东西的测试方法没有真正的意义。

请详细说明Krishna Kuntala所说的,当您查看该类时,add处理程序正在添加一个

private final CopyOnWriteArrayList处理程序

由于第三次调用add处理程序是在条目3上,因此它将使用输出到同一文件的三个处理程序记录同一条语句。

只是为了详细说明Krishna Kuntala所说的,当您查看该类时,add处理程序是在

private final CopyOnWriteArrayList处理程序

由于您在条目3上第三次调用add处理程序,因此它将使用输出到同一文件的三个处理程序记录相同的语句。

问题在于您多次调用
writeEntryToLogFile()
并多次设置
fileHandler

将调用方法中的两行移动为:

@Test
public void infoPackage() throws Exception {
    fh = new FileHandler("test.log", true);
    fh.setFormatter(formatter); 
    logger.addHandler(fh);
    // do some test stuff
    writeEntryToLogFile("entry one");
    // do some more test stuff
    writeEntryToLogFile("entry two");
    // do even more test stuff
    writeEntryToLogFile("entry three");
}

private void writeEntryToLogFile(String message) throws Exception {
    logger.info(message);
}

问题是因为您多次调用
writeEntryToLogFile()
,并多次设置
fileHandler

将调用方法中的两行移动为:

@Test
public void infoPackage() throws Exception {
    fh = new FileHandler("test.log", true);
    fh.setFormatter(formatter); 
    logger.addHandler(fh);
    // do some test stuff
    writeEntryToLogFile("entry one");
    // do some more test stuff
    writeEntryToLogFile("entry two");
    // do even more test stuff
    writeEntryToLogFile("entry three");
}

private void writeEntryToLogFile(String message) throws Exception {
    logger.info(message);
}

作为进一步的补充说明,打印大量文本的测试方法可能会很烦人,并且会降低测试速度。这是一种selenium测试。它确实有用,但我从代码中删掉了它,因为它与我所面临的问题无关。这不是很多文本,但我想有一些随机生成的值记录下来。无论如何,您的解决方案看起来不错,但它抛出了一个空指针。我猜这是因为文件处理程序是在@test?@tom中稍后声明的。您的操作是正确的。它使问题更加明显。现在,为了指示切割代码,添加
更好。否则,您是对的。
fh=newfilehandler(“test.log”,true)应在setup()方法中执行。我更新为正确。“一些随机生成的值记录”在测试中不使用随机生成的值。当您的测试失败时,您需要相当确定这是因为某些内容被破坏或更改,而不是因为您正在测试的内容发生了更改。另外,打印大量文本的测试方法可能会很烦人,也会减慢您的测试速度。这是一种selenium测试。它确实有用,但我从代码中删掉了它,因为它与我所面临的问题无关。这不是很多文本,但我想有一些随机生成的值记录下来。无论如何,您的解决方案看起来不错,但它抛出了一个空指针。我猜这是因为文件处理程序是在@test?@tom中稍后声明的。您的操作是正确的。它使问题更加明显。现在,为了指示切割代码,添加
更好。否则,您是对的。
fh=newfilehandler(“test.log”,true)应在setup()方法中执行。我更新为正确。“一些随机生成的值记录”在测试中不使用随机生成的值。当你的测试失败时,你要相当确定这是因为某些东西被破坏或改变了,而不是因为你正在测试的东西改变了。