【发布时间】:2017-03-01 16:06:00
【问题描述】:
以下代码是概述此单元测试目标的 sn-p。下面演示了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);
}
}
编辑:
现在发生了什么:线程被创建,文件被创建,文件被删除,线程死亡,断言证明什么都没有并重复
预期结果:线程应该全部启动,并且断言应该确保一次只创建一个文件,并且其他线程正在等待,而不是执行该方法
双重编辑:
我真正需要的是对上述单元测试进行重构,以便它完成它应该做的事情(如上所述)
【问题讨论】:
-
我不太了解这个策略。为什么要检查当前目录是否为空,每次启动线程创建然后删除文件时,测试您的方法是否已同步?以及为什么要同步此方法,因为 createNewFile() 已经自动创建了一个新的空文件...(引用自 javadoc)
-
不详细说明为什么这不起作用;但指出概念上的弱点: - 没有必要“证明”
synchronized关键字有效。如:您也没有测试每个原始 int 值都可以容纳 32 位;并且没有一个只支持 31 位。因为这些都是您的应用程序范围之外的所有元素。换句话说:你可以/应该相信这样的事情。甚至当 JVM 中存在错误时:期望它是如此微妙,以至于您可以轻易想到的没有任何东西会发现此类问题。 -
-“真正的”线程安全是关于防止死锁或导致数据损坏或不一致的竞争条件。在一定程度上可以测试是的;但是测试设置需要根据您的“被测代码”的具体情况进行定制。
-
如果您的测试目标是测试发布的代码以外的其他内容,那么请展示您真正打算测试的内容。事实上,这个测试没有意义,也没有办法检查方法是否同步,因为如果它没有同步它会做完全相同的事情(因为 createNewFile 已经是线程安全的)。
-
投票重新开放。我认为您无法通过 JUnit 测试来证明它,但您可以通过在方法中添加一些代码来证明它,例如增加一个 volatile 静态计数器,并检查它一次只增加 1。
标签: java multithreading junit synchronized