为啥伴随对象不使用 JUnit 测试作为私有字段进行测试?

Posted

技术标签:

【中文标题】为啥伴随对象不使用 JUnit 测试作为私有字段进行测试?【英文标题】:Why does a companion object not test as private field with JUnit tests?为什么伴随对象不使用 JUnit 测试作为私有字段进行测试? 【发布时间】:2022-01-07 21:12:51 【问题描述】:

我最近不得不在 Kotlin 的编程课上做一个练习。我们使用与 Java 课程相同的 JUnit 测试,有时这会导致一些奇怪的问题。

在这种情况下,我们应该有一个带有静态方法的类,我们可以从另一个类访问它。由于 Kotlin 中没有静态方法,我们将使用带有注释 @JvmStatic 的伴随对象,如下所示:

companion object

        @JvmStatic

        fun parseRationalNumber[...]
...

这很好用。然而,由于我真的不知道自己在做什么,我最终将我的伴生对象命名为:

companion object Parser

        @JvmStatic

        fun parseRationalNumber[...]
...

一切仍然有效,但这最终破坏了我们的一项自动化 JUnit 测试,该测试将检查我们是否正确解决了这个练习:

@Test
    void testAllFieldsPrivate() 
        Field[] fields =  RationalNumber.class.getDeclaredFields();
        for (Field field: fields) 
            assertTrue(Modifier.isPrivate(field.getModifiers()) || "Companion".equals(field.getName()),
                    "The RationalNumber class should have only private instance variables.");
        
    

当我搜索非私有字段时,这给了我很长一段时间的问题。最后我稍微搞砸了测试,发现它有问题的字段名为“Parser”,这是我的伴生对象的名称。

当我问我的教授为什么会发生这种情况时,他无法给我答案,所以我想我会在这里问。有谁知道为什么命名的伴随对象作为非私有字段进行测试?

当我现在查看它时,测试似乎对名为“Companion”的伴随对象进行了例外处理,我认为它是未命名的伴随对象的默认名称。有人知道为什么这会作为非私有领域进行测试吗?

【问题讨论】:

不正是|| "Companion".equals(field.getName() 的不同之处吗?如果您将其更改为 || "Parser".equals(field.getName() 它可能具有相同的行为?我相信伴生对象永远不会是私有的,这就是为什么 || "Companion".equals(field.getName() 一开始就在那里 谢谢,我在发布问题后就看到了。我将问题改为询问为什么伴随对象会被视为非私有字段,因为我仍然不理解那部分。不过,您的评论确实回答了我最初的问题! 【参考方案1】:

伴随对象根本不是私有的,除非标记为私有。

因此,测试实际上明确排除了伴随对象,但它们以非常脆弱的方式进行。除了使用默认的“Companion”名称,测试还应该使用反射来获取伴随对象的实际名称。

问题是测试很可能使用 Java 反射,并且无法访问它

【讨论】:

【参考方案2】:

仅仅是因为任何未声明为私有的字段都不是私有的。伴生对象也不例外。你需要这样做

private companion object


为此

【讨论】:

我知道这听起来很简单,但感谢您的回答。一开始我从未将伴生对象视为“领域”。我只将字段视为声明变量所具有的东西。

以上是关于为啥伴随对象不使用 JUnit 测试作为私有字段进行测试?的主要内容,如果未能解决你的问题,请参考以下文章

为啥私有构造函数在案例类中仍然可见?

为啥 JUnit 中的 @Rule 注释字段必须是公开的?

为啥可以毫无问题地测试 Spock 中的私有方法/字段?

为啥我不能将此 Spring Boot 服务类注入 JUnit 测试类?预计至少有 1 个 bean 有资格作为 autowire 候选者

为啥不能在 junit 配置中添加程序参数?

JUnit 测试私有变量? [复制]