junit5 icon indicating copy to clipboard operation
junit5 copied to clipboard

Jupiter static @TempDir behaves unexpected when subclasses are run in parallel

Open Vampire opened this issue 2 years ago • 1 comments

I wanted to supply an MCVE, but I was not able to, as I was not able to find a way to influence the order in which the @TempDir handling extension initializes classes. Even a static initializer in the affected classes is executed after (!?!) the extension injected the static fields, but I try to describe the problem.

If you have a construct like

@Execution(CONCURRENT)
abstract class Base {
    @TempDir
    static Path tempDir;

    @Test
    void foo() {}
}

class A extends Base {}
class B extends Base {}

and now run A and B in parallel, the extension creates one temp directory for A and one temp directory for B. Then it sets the Base.tempDir field for the one that happens to execute first, let's call it SubFirst. Then it sets the same field for the one that happens to execute second, let's call it SubSecond, and thus overwrites the value written for SubFirst as it is a static field in Base.

Now A and B both work with the same temporary directory. This can already mean problems of course.

In my case it did not yet cause problems, as the test created a further subdirectory depending on the actual class name, so there was no conflict in the actual files created and verified.

But then, if SubSecond is finished first, its temp directory is deleted, and now SubFirst has a problem if he still used the temporary directory as suddenly its files and even the folder might be deleted already.

I guess this is hard to "do right", but it is at least majorly confusing.

I actually exepected the scope of the tempDir to be for A and B and the directory only getting deleted after all subclasses are finished executing which would have been exactly what I needed. (I solved it differently now).

Another possibility might be to either disallow static tempdir fields in concurrent specs, or to automatically add some read-write resource so that the test classes are not run in parallel.

Vampire avatar Apr 18 '22 16:04 Vampire

The semantics of @TempDir are test or class scoped. By using it as static field in a base class the semantics are engine scoped. JUnit Jupiter has no facilities for this.

The needed facilities may be introduced with #2816.

Though for @TempDir I think the better solution would be to ban the use of a static field in a base class altogether. I don't believe there is a valid use case for it that isn't handled equally well by a non-static field.

mpkorstanje avatar Apr 24 '22 14:04 mpkorstanje