java - 测试方法是否以同步方式运行

标签 java multithreading junit synchronized

以下代码是概述此单元测试目标的片段。下面演示了 createFile 只执行一个已知是线程安全操作的任务。

因此,这个想法更多的是围绕测试而不是实际操作;毫无疑问地证明线程安全方法的行为,因为它的行为方式我们已经在历史上证明过。

public static final synchronized void createFile(final File file) throws IOException {
    file.createNewFile();
}

@Test
public void testCreateFileThreadSafety() throws Exception {
    for (int i = 1; i < 50; i++) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    createFile(new File(i+".txt"));
                    new File(i+".txt").delete();
                } catch (IOException ex) {
                   System.out.println(ex.getMessage());
                }
            }
        }).start();
        assertTrue(file.getParentFile().listFiles().length == 0);
    }
}

编辑:

现在发生了什么:线程被创建,文件被创建,文件被删除,线程终止,断言什么都证明不了并重复

期望值:所有线程都应该启动,断言应该确保一次只创建一个文件,其他线程正在等待,而不是执行该方法

双重编辑:

我真正需要的是对上面的单元测试进行重构,以便它完成它应该做的事情(如上所述)

最佳答案

当然对于这个非常简单的用例来说,它是相当愚蠢的,因为同步关键字就在那里。但一般来说,如果你想测试一个方法是否从未被并发调用,你可以这样抛出:

static AtomicInteger c = new AtomicInteger();

public void knownNonThreadSafeMethod(final File file) throws IOException {
    int t = c.incrementAndGet();
    doSomething();   
    Thread.yield(); //try to force race conditions, remove in prod
    assert t == c.intValue();
}

如果您使用简单的 int i.s.o. AtomicInteger,编译器优化将删除断言。

static int c = 0;

public void knownNonThreadSafeMethod(final File file) throws IOException {
    int t = ++c;
    doSomething();   
    assert t == c; //smart-ass compiler will optimize to 'true'
}

使用 AtomicInteger,该值保证在所有 CPU 和所有线程上同步,因此您将检测到任何并发访问。

我知道它不在 JUnit 测试中,但我找不到任何非侵入性的方法来解决这个问题。也许您可以通过 AspectJ 注入(inject)它?

关于java - 测试方法是否以同步方式运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42536539/

相关文章:

java - 有没有办法判断连接是否因超时或线程死亡而退出?

java - 从父类(super class)调用方法不起作用 Java

c# - ManualResetEvent.Set() 什么时候可以返回 false?

java - 使用 Junit 5 和 Spring Boot 2 在 Mokito 2 中未发现测试

java - 测试套件在 JUnit5 中是否被认为已弃用?

java - log4j:归档文件删除策略

java - 如何仅使用给定的格式将给定的字符串转换为java中的日期?

Java Publisher Server 聊天程序

python - 为什么我的 socket.makefile 对象即使在关闭后也会阻塞?

java - 具有不可预测的外部依赖性的单元测试代码