Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal to enable @BeforeAll/@AfterAll in nested classes #166

Closed
nipafx opened this issue Feb 24, 2016 · 10 comments
Closed

Proposal to enable @BeforeAll/@AfterAll in nested classes #166

nipafx opened this issue Feb 24, 2016 · 10 comments

Comments

@nipafx
Copy link
Contributor

nipafx commented Feb 24, 2016

As far as I can tell the reason to have nested test classes be static is that you usually want to build on the outer class(es)' structure and state. Unfortunately this bars the use of @BeforeAll/@AfterAll in nested classes. If it is considered beneficial to enable their use, the following could be a way to go:

  • Alternatively allow static nested classes.
  • Create a parameter injector that injects instances of the outer classes.

This might look as follows:

class Outer {

    AwesomeClass unitUnderTest  ;

    @Nested
    static class InnerTest {

        @BeforeAll
        // 'Outer' instances can not be injected
        // because it makes no sense to operate on them 
        static void initAll() {
            // ...
        }

        @BeforeEach
        // an 'Outer' instances is created;
        // all '@BeforeEach' methods are run on/with;
        // it is injected here
        static void init(Outer outer) {
            outer.unitUnderTest.prepareYourThing();
        }

        @Test
        // same as with 'init'
        static void testThatThing(Outer outer) {
            outer.unitUnderTest.doYourThing();
        }

    }

}

Because this makes nested tests more verbose, it should be an alternative for the scenarios where it is direly needed. The default way to go would be non-static nested classes because the need for @BeforeAll/@AfterAll is comparatively rare (in my experience).

@jlink
Copy link
Contributor

jlink commented Feb 24, 2016

I'd vote against nested static classes. If you really really need before/afterAll behaviour in nested tests just use an extension.

Von meinem iPad gesendet

Am 24.02.2016 um 21:39 schrieb Nicolai Parlog notifications@github.com:

As far as I can tell the reason to have nested test classes be static is that you usually want to build on the outer class(es)' structure and state. Unfortunately this bars the use of @BeforeAll/@afterall in nested classes. If it is considered beneficial to enable their use, the following could be a way to go:

Alternatively allow static nested classes.
Create a parameter injector that injects instances of the outer classes.
This might look as follows:

class Outer {

@Nested
static class InnerTest {

    @BeforeAll
    // 'Outer' instances can not be injected
    // because it makes no sense to operate on them 
    static void initAll() {
        // ...
    }

    @BeforeEach
    // an 'Outer' instances is created;
    // all '@BeforeEach' methods are run on/with;
    // it is injected here
    static void init(Outer outer) {
        outer.unitUnderTest.prepareYourThing();
    }

    @Test
    // same as with 'init'
    static void testThatThing(Outer outer) {
        outer.unitUnderTest.doYourThing();
    }

}

}
Because this makes nested tests more verbose, it should be an alternative for the scenarios where it is direly needed. The default way to go would be non-static nested classes because the need for @BeforeAll/@afterall is comparatively rare (in my experience).


Reply to this email directly or view it on GitHub.

@bechte
Copy link
Contributor

bechte commented Feb 25, 2016 via email

@nipafx
Copy link
Contributor Author

nipafx commented Feb 26, 2016

Could you give us a better understanding of your use-case by telling about the situation in which you wanted to use nested static classes?

I don't have one. 😉

@jlink's talk and @BeforeAll's Javadoc made it seem as if the reason why @...All were not supported in nested classes was purely technical. This is a proposal for a solution to that technical problem, not a feature request.

@bechte
Copy link
Contributor

bechte commented Feb 26, 2016 via email

@marcphilipp
Copy link
Member

When you have multiple levels of nesting, e.g. a static inner class inside another static class and so on, this would become challenging to use and implement. You would need multiple parameters in your @BeforeAll methods.

Anyway, I'm with @jlink and @bechte on this one: I don't see a compelling use case and therefore I'm closing this issue for now.

@ahrytsiuk
Copy link

I totally agree that we should avoid @BeforeAll and @AfterAll callbacks in the @Nested test classes.

But anyway you can implement them

@sbrannen
Copy link
Member

@ahrytsiuk, that's quite an interesting hack you've used there, having an @Nested inner class extend a static nested class just to be able to declare static @BeforeAll and @AfterAll methods. 😱

@hjohn
Copy link

hjohn commented Feb 4, 2020

Thanks @ahrytsiuk -- just what I needed.

@gortiz
Copy link

gortiz commented Jun 22, 2020

I really find this feature useful. In my company we have several custom extensions designed to be used with @RegisterExtension. Some of them have to do heavy task like starting services using docker or executing DDLs on a database. To make tests faster we try to do this things on BeforeAllCallback.beforeAll. Usually we register these extensions at the upper class, so there is no problem with this approach. But sometimes it is necessary to do it on a nested class. We have designed the extensions thinking that beforeAll will be called before beforeEach.

Therefore, when we add this extensions in a nested class we get very strange behaviors (usually NPE). There are ways to avoid the problem. Use nested classes that extend a static class, as proposed by @ahrytsiuk, would work but seems quite cheesy. Our approach was to do not use nested classes or dynamic test at all, as the behavior is not the one we expect (even when the class is annotated with @testinstance(PER_CLASS)).

@gileli121
Copy link

gileli121 commented Oct 1, 2020

I am not sure that it is written here but this will work:

public class MyTestClass {

    @Nested
    @TestInstance(TestInstance.Lifecycle.PER_CLASS) // You must add this!
    public class TestsType1 {

        @BeforeAll
        public void beforeAll() {
            System.out.println("before all");
        }
        
        @Test
        public void test1_a() {
            System.out.println("test1_a");
        }
        @Test
        public void test2_a() {
            System.out.println("test2_a");
        }
    }
}

This will work because of @TestInstance(TestInstance.Lifecycle.PER_CLASS)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants