4.1 @Disabled

Now let's look at some very useful and popular annotations of the JUnit framework. The first annotation allows you to turn off a specific test so that JUnit does not call it. It is needed in cases where you notice that the test is not working correctly, or you change the code and the test accidentally breaks.

As I wrote earlier, 99% of the tests are not supported by anyone, so they all turn out to be disabled sooner or later. Therefore, this annotation is the first in the list of useful ones.

Consider her example:

public class AppTest {

    @Disabled("Test is temporarily disabled. True, true")
    @Test
    void testOnDev(){
        System.setProperty("ENV", "DEV");
        Assumptions.assumeFalse("DEV".equals(System.getProperty("ENV")));
    }

    @Test
    void testOnProd(){
     System.setProperty("ENV", "PROD");
        Assumptions.assumeFalse("DEV".equals(System.getProperty("ENV")));
    }
}

In the example above, the method testOnDev()will not be called. By the way, the annotation @Disabledcan be written immediately before the class declaration, then all its methods will be ignored.

@Disabled("Temporarily turned off the test, we will fix it by May 2001")
public class AppTest {
    @Test
    void testOnDev(){
        System.setProperty("ENV", "DEV");
        Assumptions.assumeFalse("DEV".equals(System.getProperty("ENV")));
    }

    @Test
    void testOnProd(){
     System.setProperty("ENV", "PROD");
        Assumptions.assumeFalse("DEV".equals(System.getProperty("ENV")));
    }
}

4.2 @Nested

JUnit allows you to call test methods on nested classes. I mean nested test classes. It is not a fact that you will often encounter them, but there is such a possibility, so you need to understand what it is.

To call the methods of a nested class before its declaration, you need to write an annotation @Nested. Example:

public class AppTest {
    @Nested
    public class DevStagingEnvironment {
    @Test
        void testOnDev(){
            System.setProperty("ENV", "DEV");
            Assumptions.assumeFalse("DEV".equals(System.getProperty("ENV")));
        }
   }

    @Nested
    public class ProductionEnvironment {
        @Test
        void testOnProd(){
           System.setProperty("ENV", "PROD");
           Assumptions.assumeFalse("DEV".equals(System.getProperty("ENV")));
        }
   }
}

More details can be found in the official documentation .

4.3 @ExtendWith

Another useful annotation is @ExtendWith. Most likely you will meet her very often, so let's look at her in more detail.

JUnit is a powerful framework that allows you to write various plugins (extensions) for flexible customization of your work. Some extensions can collect statistics about tests, others can emulate an in-memory file system, others can emulate working inside a web server, and so on.

If your code is running inside a framework (for example, Spring), then almost always this framework manages the creation and configuration of objects in your code . Therefore, a special test plugin is indispensable. Examples:

Example 1. The extension WebServerExtensionpasses to the called test method URLin order to work correctly.

@Test
@ExtendWith(WebServerExtension.class)
void getProductList(@WebServerUrl String serverUrl) {
    WebClient webClient = new WebClient();
    // Use WebClient to connect to web server using serverUrl and verify response
    assertEquals(200, webClient.get(serverUrl + "/products").getResponseStatus());
}

This is how tests usually start to test code that works with the Spring framework:

@ExtendWith(SpringExtension.class)
@ExtendWith(MockitoExtension.class)
class TestServiceTest {

    @MockBean
    TestService service;

    @Test
    void test() {
        assertNotNull(service); // Test succeeds
    }
}

SpringExtensioncreates a test version of the Spring framework, but MockitoExtentionallows you to create fake objects. Fake objects is a very interesting topic, we will definitely touch on it, but a little later.

4.4 @Timeout

Let's finish this lecture with a small and interesting annotation @Timeout. It allows you to set the time to run the test. If the test took more time than specified in the annotation, then it is considered failed.

class TimeoutDemo {
    @Test
    @Timeout(value = 100, unit = TimeUnit.MILLISECONDS)
    void failsIfExecutionTimeExceeds100Milliseconds() {
        // test will fail if it takes more than 100 milliseconds
    }
}

This concludes our lecture.