Home > database >  Why does a companion object not test as private field with JUnit tests?
Why does a companion object not test as private field with JUnit tests?

Time:12-01

I had to do an exercise for a programming class in Kotlin recently. We use the same JUnit tests as the Java course and sometimes this leads to some strange issues.

In this case we were supposed to have a class with a static method that we would access from another class. Since there are no static methods in Kotlin, we were to use a companion object with the annotation @JvmStatic, like so:

companion object{

        @JvmStatic

        fun parseRationalNumber[...]{
...}
}

This works fine. However, since I didn't really know what I was doing I ended up naming my companion object like this:

companion object Parser{

        @JvmStatic

        fun parseRationalNumber[...]{
...}
}

Everything still worked, but this ended up breaking one of our automated JUnit tests which would check if we solved the exercise correctly:

@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.");
        }
    }

This gave me issues for a long time as I searched for fields that weren't private. In the end I messed around with the test a bit and found out that the field it had issues with was called "Parser", which was the name of my companion object.

When I asked my professor about why this happened, he couldn't give me an answer, so I figured I'd ask here. Does anyone know why the named companion object tested as a non-private field?

When I look at it now, the test seems to make an exception for a companion object called "Companion", which I would assume is the default name for an unnamed companion object. Does anybody know why this would test as a non-private field?

CodePudding user response:

Simply because any field not declared as private isn't private. companion objects are no exception. You would need to do

private companion object{

}

for that

CodePudding user response:

Companion objects simply aren't private unless marked as such.

The test actually explicitly excludes the companion object because of that, but they do it in a really brittle way. Instead of using the default "Companion" name, the test should also use reflection to get the actual name of the companion object.

The problem is that most likely the test is using Java reflection, and wouldn't have access to that

  • Related