【问题标题】:Mocking and Handling Map.Entry when it is returned from a method call从方法调用返回时模拟和处理 Map.Entry
【发布时间】:2019-08-28 17:04:31
【问题描述】:

总结:当从方法调用返回时,我对如何处理单个“Map.Entry”感到困惑。在我的具体情况下,我需要对此进行模拟(目前使用模拟),但我的问题是关于如何将“Map.Entry”作为一个单元处理,而不是关于模拟它......两者的帮助都会很大赞赏。

=============================

我有如下方法。我需要创建一个匹配的实体(我假设为 Map.Entry),以便在调用该方法时返回模拟。我不知道如何创建一个 Map.Entry。我已经将调用一直追溯到对 db 的 sql 调用,但只能找到将返回的 Object 强制转换为 Map.Entry 的点。

没有说明如何构建这样的东西。我需要有关如何构建可由模拟返回的单个“Map.Entry”的帮助。

 public Map.Entry<Date,Boolean> getLastModified(SomeClass someClass)
    throws Exception
    {
        return clusterViewDataProvider.getClusterModified(someClass);
    }

这是为我创建模拟对象的行。为简单起见,假设上面的方法在“Foo”类中。

Foo foo = mock(Foo.class);

然后我需要这样的东西来说明当方法被调用(作为模拟)时,它应该返回我需要构建的“Map.Entry”。

when(foo.getLastModifiedGid(any())).thenReturn(the Map.Entry I don't know how to make yet);

最后,我需要对返回的 Map.Entry 进行一些可测试的断言。我可以检查断言中的键和值 - 没有比这更重要的了 - 再次,我不确定如何将其作为单个 Map.Entry 访问......

assertTrue(The Key == SomeDate)
assertTrue(The Value == True)

如果我对任何事情不清楚,请发表评论,我会澄清。格拉齐。

【问题讨论】:

  • 转到 Map.Entry 的 javadoc:docs.oracle.com/javase/8/docs/api/java/util/Map.Entry.html。查看列表 f 实现类。选择您喜欢的那个。创建该类的实例。
  • 如何将 Map.Entry 放入 HashMap?我如何接受该方法的返回值?我可能使用哪个实现类的实例并不重要,但我不清楚代码会是什么样子,在这种情况下阅读文档并不是很有用。代码示例将不胜感激。这个链接表明它并不简单......stackoverflow.com/questions/39441096/…
  • when(foo.getLastModifiedGid(any())).thenReturn(new AbstractMap.SimpleEntry(someKey, someValue))
  • @JBNizet 非常感谢!
  • 我还发现了这种方法来创建我的“由模拟返回的对象” Map.Entry me = new AbstractMap.SimpleImmutableEntry (new Date(), Boolean.TRUE);

标签: java unit-testing collections


【解决方案1】:

无需创建自己的Map.Entry 实现。您可以使用现有的实现之一,例如 AbstractMap.SimpleEntry:

Date date = new Date();
boolean value = true;

Map.Entry<Date, Boolean> entry =  new AbstractMap.SimpleEntry<>(date, value);
when(foo.getLastModifiedGid(any())).thenReturn(entry);

AbstractMap.SimpleImmutableEntry

Map.Entry<Date, Boolean> entry =  new AbstractMap.SimpleImmutableEntry<>(date, value);

附带说明,java.util 中的日期类已过时,java.time 中的类应用于 Java 8+。具体来说,java.util.Datejava.time.Instant 替换。

【讨论】:

  • 关于 java.time 的要点。即使对于 Java 6 和 Java 7,使用后向端口库 ThreeTen-Backport 也比使用糟糕的旧日期时间类(如 Date)要好。
  • 同意 - 我正在嘲笑应该很久以前编写的单元测试的遗留代码 - 因此使用 Date...
【解决方案2】:

您可以实现自己的条目

class DummyEntry<K,V> implements Map.Entry<K, V> {

        K key;
        V value;

        public DummyEntry(K key, V value) {
            this.key = key;
            this.value = value;
        }

        @Override
        public K getKey() {
            return key;
        }

        @Override
        public V getValue() {
            return value;
        }

        @Override
        public V setValue(V value) {
            this.value = value;
            return value;
        }
    }

然后在你的模拟中返回它。

when(foo.getLastModifiedGid(any())).thenReturn(new DummyEntry(...))

【讨论】:

    【解决方案3】:

    构建您自己的自定义 Entry 类需要大量额外的代码实现,仅用于测试情况

    这应该是设计测试的一个危险信号,因为您可能使问题变得比需要的复杂得多。

    相反,为什么不创建一个实际的地图并让地图完成工作?

        //define your expected response element
        Date foo = ...;
        Boolean bar = ...;
    
        //instantiate map
        Map<Date,Boolean> dummyMap = new HashMap<>();
        dummyMap.put(foo, bar);
    
        //fetch an actual working copy from a functional map
        Map.Entry<Date, Boolean> baz = dummyMap.entrySet().stream().findFirst().get();
    
        //mock away
        when(foo.getLastModifiedGid(any())).thenReturn(baz);
    

    我有点困惑为什么你会断言关于条目本身的一些东西。如果你定义它,它应该是你的。如果您的测试方法改变了它,请测试它的结果,而不是您提供的罐头对象。

    【讨论】:

    • 我同意测试条目的问题 - 在这种情况下,我正在模拟数据库上的“命中” - 我不想在单元测试中命中数据库,因为我'我相信你会同意......对数据库的这种“打击”有几个层次,我想我正在做的是“测试”,中间没有任何东西会改变这个深层调用返回的东西......有时我觉得像这样编写测试并不是我时间的最佳利用,但公司规则要求高代码覆盖率 - 所以我编写它们......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-03
    • 1970-01-01
    • 2018-04-27
    • 2014-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多