{"id":13413,"date":"2018-05-28T22:46:00","date_gmt":"2018-05-28T20:46:00","guid":{"rendered":"http:\/\/touk.pl\/blog\/?guid=5ab86764dcc1746d92c9b564359e6af9"},"modified":"2022-08-01T09:30:09","modified_gmt":"2022-08-01T07:30:09","slug":"testing-kotlin-with-spock-part-2-enum-with-instance-method","status":"publish","type":"post","link":"https:\/\/touk.pl\/blog\/2018\/05\/28\/testing-kotlin-with-spock-part-2-enum-with-instance-method\/","title":{"rendered":"Testing Kotlin with Spock Part 2 &#8211; Enum with instance method"},"content":{"rendered":"<h1 id=\"testing-kotlin-with-spock-part-2---enum-instance-method\"><span id=\"testing-kotlin-with-spock-part-2-enum-instance-method\">Testing Kotlin with Spock Part 2 &#8211; Enum instance method<\/span><\/h1>\n<p>The enum class with instance method in Kotlin is quite similar to its Java version, but they are look a bit different in the bytecode. Let&#8217;s see the difference by writing some tests using <a href=\"http:\/\/spockframework.org\/\">Spock<\/a>.<\/p>\n<h2 id=\"what-do-we-want-to-test\">What do we want to test?<\/h2>\n<p>Let&#8217;s see the code that we want to test:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\">enum class EnumWithInstanceMethod {\r\n    PLUS {\r\n        override fun sign(): String = \"+\"\r\n    },\r\n    MINUS {\r\n        override fun sign(): String = \"-\"\r\n    };\r\n\r\n    abstract fun sign(): String\r\n}\r\n<\/pre>\n<p>Obviously, it can be written in a better way (e. g. using enum instance variable), but this example shows the case we want to test in the simplest way.<\/p>\n<h2 id=\"how-to-test-it-with-spock\">How to test it with Spock?<\/h2>\n<h3 id=\"the-simplest-test-that-does-not-work\">The simplest test (that does not work)<\/h3>\n<p>First, we can write the test like we would do it with a Java enum:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">def \"should use enum method like in java\"() {\r\n    expect:\r\n        EnumWithInstanceMethod.MINUS.sign() == '-'\r\n}\r\n<\/pre>\n<p>The test fails:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">Condition failed with Exception:\r\n\r\nEnumWithInstanceMethod.MINUS.sign() == '-'\r\n                             |\r\n                             groovy.lang.MissingMethodException: No signature of method: static com.github.alien11689.testingkotlinwithspock.EnumWithInstanceMethod$MINUS.sign() is applicable for argument types: () values: []\r\n                             Possible solutions: sign(), sign(), is(java.lang.Object), find(), with(groovy.lang.Closure), find(groovy.lang.Closure)\r\n\r\n\r\n    at com.github.alien11689.testingkotlinwithspock.EnumWithInstanceMethodTest.should use enum method like in java(EnumWithInstanceMethodTest.groovy:11)\r\nCaused by: groovy.lang.MissingMethodException: No signature of method: static com.github.alien11689.testingkotlinwithspock.EnumWithInstanceMethod$MINUS.sign() is applicable for argument types: () values: []\r\nPossible solutions: sign(), sign(), is(java.lang.Object), find(), with(groovy.lang.Closure), find(groovy.lang.Closure)\r\n    ... 1 more\r\n<\/pre>\n<p>Interesting&#8230; Why is Groovy telling us that we are trying to call a static method? Maybe we are not using the enum instance but something else?. Let&#8217;s create a test where we pass the enum instance to method:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">static String consume(EnumWithInstanceMethod e) {\r\n    return e.sign()\r\n}\r\ndef \"should pass enum as parameter\"() {\r\n    expect: consume(EnumWithInstanceMethod.MINUS) == '-'\r\n}<\/pre>\n<p>Error message:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">Condition failed with Exception:\r\n\r\nconsume(EnumWithInstanceMethod.MINUS) == '-'\r\n|\r\ngroovy.lang.MissingMethodException: No signature of method: static com.github.alien11689.testingkotlinwithspock.EnumWithInstanceMethodTest.consume() is applicable for argument types: (java.lang.Class) values: [class com.github.alien11689.testingkotlinwithspock.EnumWithInstanceMethod$MINUS]\r\nPossible solutions: consume(com.github.alien11689.testingkotlinwithspock.EnumWithInstanceMethod)\r\n\r\n\r\n    at com.github.alien11689.testingkotlinwithspock.EnumWithInstanceMethodTest.should pass enum as parameter(EnumWithInstanceMethodTest.groovy:29)\r\nCaused by: groovy.lang.MissingMethodException: No signature of method: static com.github.alien11689.testingkotlinwithspock.EnumWithInstanceMethodTest.consume() is applicable for argument types: (java.lang.Class) values: [class com.github.alien11689.testingkotlinwithspock.EnumWithInstanceMethod$MINUS]\r\nPossible solutions: consume(com.github.alien11689.testingkotlinwithspock.EnumWithInstanceMethod)\r\n    ... 1 more\r\n<\/pre>\n<p>Now we see that we passed the class <code>com.github.alien11689.testingkotlinwithspock.EnumWithInstanceMethod$MINUS<\/code>, not the enum instance.<\/p>\n<h3 id=\"but-it-works-in-java\">But it works in Java&#8230;<\/h3>\n<p>Analogous code in JUnit works perfectly and the test passes:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">@Test\r\npublic void shouldReturnSign() {\r\n    assertEquals(\"-\", EnumWithInstanceMethod.MINUS.sign());\r\n}\r\n<\/pre>\n<p>Java can access Kotlin&#8217;s instance method without problems, so maybe something is wrong with Groovy&#8230;<\/p>\n<p>But the Java enum with instance method, e. g.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">public enum EnumWithInstanceMethodInJava {\r\n    PLUS {\r\n        public String sign() {\r\n            return \"+\";\r\n        }\r\n    },\r\n    MINUS {\r\n        public String sign() {\r\n            return \"-\";\r\n        }\r\n    };\r\n\r\n    public abstract String sign();\r\n}\r\n<\/pre>\n<p>works correctly in the Spock test:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">def \"should use enum method\"() {\r\n    expect:\r\n        EnumWithInstanceMethodInJava.MINUS.sign() == '-'\r\n}\r\n<\/pre>\n<h3 id=\"whats-the-difference\">What&#8217;s the difference?<\/h3>\n<p>We can spot the difference just by looking at the compiled classes:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">$ tree build\/classes\/main\/\r\nbuild\/classes\/main\/\r\n\u2514\u2500\u2500 com\r\n    \u2514\u2500\u2500 github\r\n        \u2514\u2500\u2500 alien11689\r\n            \u2514\u2500\u2500 testingkotlinwithspock\r\n                \u251c\u2500\u2500 AdultValidator.class\r\n                \u251c\u2500\u2500 EnumWithInstanceMethod.class\r\n                \u251c\u2500\u2500 EnumWithInstanceMethodInJava$1.class\r\n                \u251c\u2500\u2500 EnumWithInstanceMethodInJava$2.class\r\n                \u251c\u2500\u2500 EnumWithInstanceMethodInJava.class\r\n                \u251c\u2500\u2500 EnumWithInstanceMethod$MINUS.class\r\n                \u251c\u2500\u2500 EnumWithInstanceMethod$PLUS.class\r\n                \u251c\u2500\u2500 Error.class\r\n                \u251c\u2500\u2500 Ok.class\r\n                \u251c\u2500\u2500 ValidationStatus.class\r\n                \u2514\u2500\u2500 Validator.class<\/pre>\n<p>Java generates anonymous classes (<code>EnumWithInstanceMethodInJava$1<\/code> and <code>EnumWithInstanceMethodInJava$2<\/code>) for the enum instances, but Kotlin names those classes after the enum instances names (<code>EnumWithInstanceMethod$MINUS<\/code> and <code>EnumWithInstanceMethod$PLUS<\/code>).<\/p>\n<p>How does it tie into the problem with Groovy? Groovy does not need the <code>.class<\/code> when accessing class in code, so when we try to access <code>EnumWithInstanceMethod.MINUS<\/code>, Groovy converts it to <code>EnumWithInstanceMethod.MINUS.class<\/code>, not the instance of the enum. The same problem does not occur in Java code since there is no <code>EnumWithInstanceMethodInJava$MINUS<\/code> class.<\/p>\n<h2 id=\"solution\">Solution<\/h2>\n<p>Knowing the difference, we can solve the problem of accessing Kotlin&#8217;s enum instance in our Groovy code.<\/p>\n<p>The first solution is accessing the enum instance with <code>valueOf<\/code> method:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">def \"should use enum method working\"() {\r\n    expect:\r\n        EnumWithInstanceMethod.valueOf('MINUS').sign() == '-'\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>The second way is to tell Groovy explicitly that we want to access the static field which is the instance of enum:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"groovy\">def \"should use enum method\"() {\r\n    expect:\r\n        EnumWithInstanceMethod.@MINUS.sign() == '-'\r\n}\r\n<\/pre>\n<p>You can choose either solution depending on style of your code and your preferences.<\/p>\n<h2 id=\"show-me-the-code\">Show me the code<\/h2>\n<p>Code is available <a href=\"https:\/\/github.com\/alien11689\/testing-kotlin-with-spock\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"The enum class with instance method in Kotlin is quite similar to its Java version, but they are look a bit different in the bytecode. Let&#8217;s see the difference by writing some tests using Spock.What do we want to test?Let&#8217;s see the code that we want to&#8230;\n","protected":false},"author":54,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[50,68,556,411,643,30],"class_list":{"0":"post-13413","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-development-design","7":"tag-groovy","8":"tag-java","9":"tag-kotlin","10":"tag-spock","11":"tag-syntax","12":"tag-testing"},"_links":{"self":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/13413","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/users\/54"}],"replies":[{"embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/comments?post=13413"}],"version-history":[{"count":13,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/13413\/revisions"}],"predecessor-version":[{"id":14733,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/13413\/revisions\/14733"}],"wp:attachment":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/media?parent=13413"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/categories?post=13413"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/tags?post=13413"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}