3

As a heavy TestNG user, this is not a problem, since @{Before,After}Class methods are not static...

But in JUnit, they are.

And this is quite a problem for what I am currently doing.

I am writing assertions for java.nio.file.Path for assertj, which uses JUnit 4.x for tests. Some assertions require that I initialize a FileSystem (a memoryfs to be precise) to test them; such a filesystem should, ideally, be initialized at the test class level and not per test. And depending on the test class, I need to initialize the contents of that filesystem differently.

Right now however, I use @Before/@After since I don't know better...

Again, with TestNG, not a problem, since @{Before,After}Class are not static. So, how do you do this with JUnit? .

fge
  • 119,121
  • 33
  • 254
  • 329
  • Similar issue is over [here](http://stackoverflow.com/questions/2825615/junit-before-class-non-static) and accepted answer seems recommendation to use testng or a hack with @RunWith(MyClass.class) :( – SMA Jan 01 '15 at 09:27
  • @almasshaikh eh, so you are a TestNG user too ;) Anyway, here I don't have a choice... I see that an answer suggests a constructor, I may go with that. I just wondered whether there would be a builtin mechanism. When you use TestNG, using JUnit _really_ feels like a step backwards :/ – fge Jan 01 '15 at 09:35
  • Downvoter please explain – fge Jan 01 '15 at 11:30
  • @fge The question is quite unclear, and seems to jump to premature conclusions (template method approach). As always, a concrete code example (e.g. how you would write this test in TestNG) would help. – Peter Niederwieser Jan 01 '15 at 12:08
  • What is your intention? Is it that you want to require that subclass impls take action before/after class? – Bohemian Jan 01 '15 at 12:29
  • @PeterNiederwieser _unclear_? I believe that I have expressed my need pretty well myself – fge Jan 01 '15 at 15:43
  • @Bohemian yes, exactly – fge Jan 01 '15 at 15:43
  • @fge You expressed a (flawed) solution rather than the problem, and your words leave a lot of guesswork. Also the question has been asked before. Anyway, a class rule is likely the best solution. – Peter Niederwieser Jan 01 '15 at 18:26
  • @PeterNiederwieser what flawed solution? The need was pretty well explained: I need a `FileSystem` for some test classes and I need it to be initialized only once per test class. What is not clear in that? – fge Jan 01 '15 at 18:29
  • 1
    Read the title and (most of) the body of your question. It's all about implementation details of a solution you had in mind ("@BeforeClass/@AfterClass abstract method", "methods are not static", etc.), rather than explaining the real problem. Also you didn't explain why the most direct solution (having a `@BeforeClass` in each test class, without a common base class) isn't good enough in your case. (You didn't even mention that there is a base class; again this has to be inferred from the context.) Of course readers can make educated guesses on all these things, but they shouldn't have to. – Peter Niederwieser Jan 01 '15 at 18:40
  • (Presenting a model TestNG solution that you want to "recreate" in JUnit would have answered most of these questions.) – Peter Niederwieser Jan 01 '15 at 18:48

1 Answers1

3

You can create a rule class for your initialization:

public class Resource extends ExternalResource {
    protected void before() {
        // ...
    }

    protected void after() {
        // ...
    }
}

and then reference it in each test:

@ClassRule public static Resource resource = new Resource();

Any per-test customisation can be done by making resource an anonymous inner class and overriding methods, or passing parameters to its constructor.

If you have a common base class, you can put resource in there, and then only declare it in subclasses that need to customize it. In junit, class rules in subclasses will override class rules in a parent class with the same name.

fgb
  • 18,439
  • 2
  • 38
  • 52
  • Hmm, so, let's say that I have a `FileSystem` to create; I'd create it in the constructor, set it up in `before()` and close it in `after()`, is that it? Then how do I access it? Do I make a getter on the instance? – fge Jan 01 '15 at 12:01
  • @fge Yes, save an instance in the constructor or the before method, and add a getter. – fgb Jan 01 '15 at 12:08
  • OK, it works. Thanks! But frankly, whoever decided that per-class test resources had to be `static` should have been killed at birth. – fge Jan 01 '15 at 16:54
  • It needs to be static, as otherwise a separate rule would be created for each test method. – Peter Niederwieser Jan 01 '15 at 18:30
  • @PeterNiederwieser coming from a TestNG background, this is a pretty severe limitation ;) – fge Jan 01 '15 at 18:33
  • TestNG reuses the test object for every test method, so class-based setup can be done in a non-static method. JUnit creates a new instance of the test class for every method, so class-based setup needs to involve statics. JUnit creates a new instance of your class for each test to limit the likelihood that one test method could pass/fail depending on whether another test method was called first. – NamshubWriter Jan 02 '15 at 17:08