2

I wish to know how can I mock kotlin final class with PowerMock so I can test it. I followed guide for testing Java final classes but I still got this error

Cannot subclass final class

Is there any way to do that?

henorek
  • 472
  • 5
  • 19
  • Just to be precise: I guess what you mean is: you want to mock a final class X; so that you can test some other class Y that makes use of X. You see, in order to test X, you would not need to mock X itself. Unfortunately, I don't have an answer for you, but a warning: yes, PowerMock allows you to mock final classes or static methods; but on the other hand, be prepared to face **all kind of strange problems**. Only only turn to PowerMock if you really really can't change your "Input code" (for example by getting rid of the "final" modifier). – GhostCat Jun 27 '16 at 11:34
  • @Jägermeister I haven't used PowerMock before. What are some strange problems you could face? – nhaarman Jun 27 '16 at 12:30
  • 4
    PowerMock manipulates byte code. So first of all, you are not testing **your class** files, but something that PowerMock created out of them. Then: as PowerMock instruments bytecodes, it conflicts with other frameworks that rely on that; for example coverage tools. Then finally: I have spent endless hours debugging "strange" fails from PowerMock test cases, **never** finding any real problem in my code. PowerMock is like an assault rifle with a broken safety switch: it works most of the time, but don't be angry/surprised if it puts a bullet in your head accidentally from time to time. – GhostCat Jun 27 '16 at 12:57
  • Are you using the @PrepareForTest(::class) annotation on your test class? – Daveloper87 Dec 21 '16 at 21:08

2 Answers2

3

With Mockito 2.1.0+ you can mock final classess as well. This feature is optional, so you have to enable it by adding Mockito extension. To do this:

  • Create a file named org.mockito.plugins.MockMaker and place it under the resources/mockito-extensions directory in your test folder.
  • The file contains a single line: mock-maker-inline

You can find more information in Mockito documentation.

Januson
  • 4,533
  • 34
  • 42
  • This extension doesn't work with Robolectric runner due to bugs in Mockito (still present, with Mockito 2.5.0) and Robolectric. There is an open pull request in Robolectric repository to fix the issue, but until it's merged, we need to stick with PowerMock. For more info, please see the issue: https://github.com/robolectric/robolectric/issues/2677 and the PR: https://github.com/robolectric/robolectric/pull/2761 – Javad Dec 30 '16 at 11:52
  • This solution works, but it slows down your tests. [You can use all-open to archive](https://engineering.21buttons.com/mocking-kotlin-classes-with-mockito-the-fast-way-631824edd5ba) the same result without a performance decrese – Brais Gabin Mar 07 '18 at 17:22
1

Just create interfaces for your classes. Than you can simply mock your classes using interface.

Ruslan
  • 14,229
  • 8
  • 49
  • 67
  • Not sure if it's a good idea to modify and pollute your main code just because of testing limitations. PowerMock and Mockito 2 can handle this limitation (see my comment on @Januson's answer regarding Mockito 2 though) – Javad Dec 30 '16 at 11:48
  • In my developer experience creating of interfaces for classes that contains some business logic is good practice most of time. – Ruslan Dec 30 '16 at 12:10
  • It's actually a controversial topic, but creating unnecessary interfaces does not always reduce coupling, it just creates boilerplate (which Kotlin aims to reduce in the first place). Coding against interfaces is good when you have multiple implementations, or it's useful from architectural point of view, or helps with dependency injection, but otherwise it complicates the code and should be avoided. Please see the comments here: http://stackoverflow.com/questions/36536727/is-it-possible-to-use-mockito-with-kotlin-without-open-the-class – Javad Dec 30 '16 at 12:51