2

Is there a way to change the return value of the property accessor called when running unit tests? Like mocking the result of the property settingsState?

I am learning to create unit tests. What that class makes is to bring stored data into the program, this data is given in a visual form. In my test, I want to define what is going on there because the window won't open there.

// top-level declaration outside class
val settingsState: ApplicationSettingsState
    get() = ServiceManager.getService(ApplicationSettingsState::class.java)
Michael Piefel
  • 18,660
  • 9
  • 81
  • 112
Ricardo
  • 91
  • 5

2 Answers2

2

settingsState is not a variable. It is a property.

I am not aware of any way to mock global properties (or global functions). The way mocking works is to cleverly create an object that looks a bit like the object to mock from the outside, but behaves differently on the inside. In the absence of an object to mock, there is no way to mock.

That said, on the bytecode level there are no global variables, properties, whatever. They are all wrapped into classes, because the JVM likes it that way. Some clever bytecode manipulation might be able to achieve some effect – but not MockK.

You can mock the property if you have a mocked object. To paraphrase the documentation:

val mock = mockk(Bus())
every { mock getProperty "speed" } returns 33
Michael Piefel
  • 18,660
  • 9
  • 81
  • 112
1

Yes you can. You want to mock a property that is declared at top-level. Top-level code in a given Kotlin file MyFile.kt is actually compiled to be inside the class MyFileKt. Let's say we have following Kotlin file named MyFile.kt:

package foo

val bar = "some value"

If we compile this file to JVM bytecode and then decompile the result to Java, we get a Java class that looks similar to this:

package foo;

public final class MyFileKt {
   private static final String bar = "some value";

   public static final String getBar() {
      return bar;
   }
}

As you can see, our top-level val we defined earlier is actually translated to a static field with associated getter in the class MyFileKt.


TLDR; Getting back to our original problem, all you need to do is statically mock this field:

mockkStatic("foo.MyFileKt") // Fully-qualified name of the generated class
every { bar } returns "some other test value" // Define what our top-level property should return

The same also works for top-level functions, of course.

Jocbe
  • 63
  • 7