Please answer the following questions for yourself before submitting an issue.
Using mockkConstructor for File should work as expected.
java.lang.StackOverflowError occurrs
Please help provide information about the failure if this is a bug. If it is not a bug, please remove the rest of this template.
Please provide detailed steps for reproducing the issue.
File using mockkConstructorPlease provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.
Please include any relevant log snippets or files here.
// -----------------------[ YOUR STACK STARTS HERE ] -----------------------
Exception in thread "main" java.lang.StackOverflowError
at io.mockk.impl.instantiation.JvmConstructorMockFactory$ConstructorInvocationHandler.invocation(JvmConstructorMockFactory.kt:81)
at io.mockk.proxy.jvm.advice.BaseAdvice.constructorDone(BaseAdvice.kt:33)
at java.io.File.<init>(File.java:374)
at sun.misc.URLClassPath$FileLoader.getResource(URLClassPath.java:1279)
at sun.misc.URLClassPath.getResource(URLClassPath.java:239)
at java.net.URLClassLoader$1.run(URLClassLoader.java:365)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at io.mockk.impl.instantiation.JvmConstructorMockFactory$ConstructorInvocationHandler.invocation(JvmConstructorMockFactory.kt:81)
// -----------------------[ YOUR STACK TRACE ENDS HERE ] -----------------------
// -----------------------[ YOUR CODE STARTS HERE ] -----------------------
package io.mockk.gh
import io.mockk.every
import io.mockk.mockkConstructor
import org.junit.Assert.assertTrue
import org.junit.Test
import java.io.File
class FileTest {
@Test
fun testConstructorMockkForFile() {
mockkConstructor(File::class) {
every {
anyConstructed<File>().exists()
} returns true
}
assertTrue(File("x").exists())
}
}
// -----------------------[ YOUR CODE ENDS HERE ] -----------------------
I performed pretty decent coding effort to make it work.
First, my goal was to solve a problem in general by protecting mockk from recursive calls to Java Library. This didn't help to solve File issues. It is too tightly coupled to a classloader. Not sure I need to merge this code at all. Will keep it in a branch.
Then I ended up with a solution that scans stack trace and detects the previous call of File method(actually any method alike) if it is a call from Java internals it allows to process it as a regular call. It works, but performance degradation is way too big. Alike 13 seconds for the code you've posted.
In general, this integration topic with JVM is a way too complex. I decided to deal with it on best effort basis. Not forbidding it, but not saying that all possible combinations are supported. So that's it. My best efforts. By closing this issue I conclude that it is very hard to achieve this and is not supported for now.
Thank you very much for trying to solve it on so short notice and the detailed explanation!
I found a solution in between by using the TemporaryFolder of jUnit, which makes mocking File some kind of obsolete.
Happens with URL class as well.
Regarding files, I have had success testing files using an in-memory filesystem (as long as you're using nio everywhere): com.github.marschall:memoryfilesystem - no need to mock in that case.
Any chance this issue will be fixed in the future?
What is the workaround for this ?
Any news or workaround available yet? This is a bit of a blocker for us...
Most helpful comment
I performed pretty decent coding effort to make it work.
First, my goal was to solve a problem in general by protecting mockk from recursive calls to Java Library. This didn't help to solve File issues. It is too tightly coupled to a classloader. Not sure I need to merge this code at all. Will keep it in a branch.
Then I ended up with a solution that scans stack trace and detects the previous call of File method(actually any method alike) if it is a call from Java internals it allows to process it as a regular call. It works, but performance degradation is way too big. Alike 13 seconds for the code you've posted.
In general, this integration topic with JVM is a way too complex. I decided to deal with it on best effort basis. Not forbidding it, but not saying that all possible combinations are supported. So that's it. My best efforts. By closing this issue I conclude that it is very hard to achieve this and is not supported for now.