- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在服务器上运行 JUnit 测试时遇到问题。当我在我的机器上运行测试时,完全没有问题。当我在服务器上运行它时,我的所有服务器“有时”都会出现故障。这意味着有时 60% 的尝试会通过,而 40% 的测试会失败。
我正在使用 Mockito。我的测试从使用 MessageListener
模拟一些回复开始并将每个请求映射到响应,并在我正在使用的引擎盖下 Collections.synchronizedSet(new HashSet<>())
这是线程安全的。(对我的synchronizedSet的每次修改都发生在 synchronized(mySynchronizedSet){....}
中)然后,我使用 RestAssurd
获取特定 REST 端点的响应并断言一些值。
当测试失败并且我查看 Stacktrace 时,我发现我的一个映射(始终在同一个对象上)不起作用,并且我的集合中的该特定请求和响应之间没有映射,自然地,我获取null
请求此端点时。
我正在使用 Jenkins 来自动编译和运行测试,并且我会在失败时获得堆栈跟踪或我的 Printlns,否则,没有可用的调试工具。
对我来说这听起来像是一个并发问题。我的意思是我的 Collection 似乎没有时间在 RestAssurd
之前做好准备对端点的请求。我已经测试了锁、 sleep 和另一个简单的 java 并发解决方案,但它们没有帮助,而且这个问题的概率特征使我陷入了死胡同。
每一个想法都会受到赞赏。
最佳答案
从您所说的来看,您似乎对 3 个具体情况下的工作原理存在误解。
最明显的是,我什至为提及这一点而道歉,但我这样做的原因是因为我收集到你仍在学习(如果你没有仍在学习,我会进一步道歉!并且在同样的速度,你可能甚至没有用我阅读的方式暗示它,如果我读错了,很抱歉):你不是用 Jenkins 进行编译,而是用你的机器上有的任何 JDK 风格进行编译(无论是 Oracle,苹果、GCJ 等)。 Jenkins 是一个自动化工具,可以帮助您简化您希望定期运行的繁琐工作。我之所以提到这一点,是因为我知道现在的大学生在开课时都使用 IDE,无法区分编译器、运行时和 IDE。
通过使用线程安全库,它不会自动使您所做的一切本质上都是线程安全的。考虑以下示例:
final Map<Object, Object> foo = Collections.synchronizedMap(new HashMap <>());
final String bar = "bar";
foo.put(bar, new Object());
new Thread(new Runnable(){
@Override
public void run(){
foo.remove(bar);
}
}).start();
new Thread(new Runnable(){
@Override
public void run(){
if(foo.containsKey(bar)){
foo.get(bar).toString();
}
}
}).start();
无法保证第二个线程对 #get(Object)
的调用会在第一个线程对 #remove(Object)
的调用之前或之后发生。考虑一下
#containsKey(Object)
#remove(Object)
#get(Object)
此时,get(Object)
的返回值为 null,并且调用 #toString()
将导致 NullPointerDereference。你说你正在使用Set,所以这个使用Map的例子主要是为了证明一点:仅仅因为你使用的是线程安全集合,并不会自动使你所做的一切都是线程安全的。我想你正在用你的集合做一些与这种行为相匹配的事情,但没有代码片段,我只能推测。
您应该小心编写 JUnit 的方式。正确的 JUnit 测试就是所谓的“白盒”测试。换句话说,您知道测试中发生的所有事情,并且您正在显式测试仅在被测单元中发生的所有事情。被测试的单元只是您正在调用的方法 - 不是您的方法调用的方法,只有方法本身。这意味着您需要一个良好的模拟框架,并模拟被测单元可能调用的任何后续方法调用。一些不错的框架有JMockit、Mockito+PowerMock等。
这一点的重要性在于您的测试应该测试您的独立代码。如果您允许网络访问、磁盘访问等,那么您的测试可能会失败,并且它可能与您编写的代码无关,并且它会使测试完全无效。在你的情况下,你暗示网络访问,所以想象一下你的交换机/路由器/等存在一些吞吐量问题,或者你的NIC缓冲区已满并且无法足够快地处理你的程序正在尝试执行的操作。当然,失败是不好的,应该修复,但是应该在“黑盒”测试中进行测试。您应该编写测试,以便消除此类问题的出现,并且仅在被测单元的特定方法中测试您的代码,而不是其他任何东西。
编辑:我实际上发布了一个关于可能相关的白盒测试的单独讨论的答案:Is using a test entity manager a legitamate testing practice?
关于java - JUnit并发访问synchronizedSet,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39834035/
我无法使用集契约(Contract)步两个线程: private Set set; ... set = Collections.synchronizedSet(new HashSet()); 并将其传
为什么会有Apache's Synchronized Set当我们有 Collection's SynchronizedSet ? 它在任何方面都更好吗? 最佳答案 这取决于你想做什么。 Apache
问题是这样的。我做了一套 Set users = Collections.synchronizedSet(new HashSet()) ... for(User u : users){ //do
我们知道,默认情况下迭代并发集合不是线程安全的,所以不能使用: Set set = Collections.synchronizedSet(new HashSet<>()); //fill with
在 REPL 中: import collection.mutable.{ HashSet, SynchronizedSet } var myPool = new HashSet[String] wi
显然,有两种方法可以获得 thread-safe HashSet使用 Java 的 Collections 的实例实用类。 Collections.newSetFromMap ( Concurrent
我正在实现我在上面找到的哈希表功能 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/
我们可以对所有 Collections 类型的对象(如 Set 和 List)使用 Collections.synchronizedCollection(Collection c),这就是为什么我们有
我运行了一个测试来为我的程序找到最佳的并发 Set 实现,使用非同步的 HashSet 作为控制,并得到了一个有趣的结果:addAll Collections.synchronizedSet(Hash
我是一名优秀的程序员,十分优秀!