当前位置: 首页 > 知识库问答 >
问题:

单元测试问题中的静态Java HashMap并发

卢黎明
2023-03-14

我有一个类(我们称之为XClass),它有一个我正在测试的方法(我们称之为xMethod)。它还包含一个:

private static Map<String, String> map = new HashMap<String, String>();

在我的单元测试设置方法中,我有:

ReflectionTestUtils.setField(xClass, "map", map, null);

在测试方法中,我创建了几个(在我的例子中是8个)线程。它们的run方法调用XClass.XMethod。此方法更改静态映射变量。方法xMethod应该调用Map.ContainsKey()Map.Get()和Map.Put()8次。它不执行任何删除操作。这个方法也不会创建任何新线程,因此线程使用XMethod完成后,不应该更改映射。我等待所有的线程完成(正常或异常)。比我查地图

int mapSize = map.size();
assertEquals("map:" + map, 8, mapSize);

它将在此处失败,并显示以下消息:

java.lang.AssertionError:map:{3=x1,2=x2,1=x3,7=x4,6=x5,5=x6,4=x7,8=x8}预期:<8>但实际:<7>

我通过使用ConcurrentHashMap解决了这个问题,但我仍然对这个问题感到困惑。怎么可能在所有8个线程完成后,映射的行为变得奇怪(size()返回7个实体,而toString()打印8个实体)?如果有7个实体并且size()方法给出了7,我就会理解了,但是映射中有8个实体。这怎么可能?!

顺便说一句,我用两种方法检查了线程的终止:
1。并检查Thread.State.Terminated。
2。我在方法返回之前打印了一个简单的消息,在线程完成之后打印了一个简单的消息(并检查没有抛出异常。这8条消息总是在第9条之前写入(在线程“完成”之后的测试中)。
3.甚至做了一个简单的线程,在run方法中包含以下逻辑:

        public void run() {
                try {
                        obj = xClass.xMethod();
                } catch (Exception e) {
                        exc = e;
                }
                finished = true;
        }

我只会无限循环直到所有的线程都完成==true。

所有这些都意味着线程在我继续断言和检查映射之前已经完成。那么,map.size()返回7个实体,而map.toString()返回8个实体又是怎么可能的呢?!

亲切的问候,
专制者

共有1个答案

糜正业
2023-03-14

通过同时对映射进行突变,您已经破坏了它的内部不变量,并且您正在观察未指定和不可预测的行为,这是预期的结果。

 类似资料:
  • 问题内容: 阅读并学习单元测试,尝试理解下面的文章,该文章解释了静态函数调用的困难。 我不清楚这个问题。我一直认为静态函数是在类中舍入实用函数的一种好方法。例如,我经常使用静态函数调用进行初始化,即: //阅读这篇文章后,我现在的目标是… 但是,我为此课程编写的几十个测试是相同的。我什么都没改变,他们仍然都过去了。难道我做错了什么? 该帖子的作者指出: 静态方法的基本问题是它们是过程代码。 我不知

  • 我需要junit测试一段代码,但它从不同类调用的GsonConverter是静态方法,我无法更改。我不知道如何进行,因为我不能嘲笑它,因为它是静态的。 下面是带有静态方法的类

  • 我试图学习如何在spring中使用Java8进行单元测试/mockito测试,但遇到了一些问题。我试图测试我的方法findUserById,但它一直运行false。可选类型问题是一个问题,但可能已经解决了这些问题。然而,它仍然是错误的。我的其他测试都是有效的,所以这只是一个顽固的测试。我将感谢你的帮助。

  • 我面临一个问题,而嘲笑jUnit测试的东西。 情况如下: 类A实现了来自第三方jar的接口,并且需要实现method1。除了method1之外,A还包含method2,它是从method1调用的。method2本身调用一些外部服务。 我想单元测试方法1。 方法1接受输入,比如X。X有一个包裹在里面的输入变量,比如var1。var1由方法1中的逻辑使用,方法1在X中设置另一个变量,比如var2。 所

  • 我正在为我的一个应用程序编写单元测试,作为一个很好的实践,我试图使我的类中的所有方法尽可能私有,所以我最终可能会使用大部分私有方法的类,很少使用公共方法,有时还会调用一些静态方法(我的其他类或一些文本,等等) 我想知道如何测试我试图只依赖Mockito和JUnit的所有类,因为Robolectric和Powermockito似乎扩展了单元测试中应该做什么的边界。我应该忽略所有私有和静态方法,以及偶

  • 我在一个外部包中有@Entity类,它也有静态元模型。在我的应用程序的服务类中,我使用这些元模型和EntityManager/criteria builder/criteria query来检索我的数据。这在运行应用程序时工作良好。然而,当运行单元测试时,我的元模型和它们的属性总是空的。 密码 我的应用程序服务类中的使用情况。。。 “RepositoryQueryBuilder”类只是一个实用程序