All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.junit.jupiter.api.extension.ExtensionContext Maven / Gradle / Ivy

There is a newer version: 5.11.4
Show newest version
/*
 * Copyright 2015-2016 the original author or authors.
 *
 * All rights reserved. This program and the accompanying materials are
 * made available under the terms of the Eclipse Public License v1.0 which
 * accompanies this distribution and is available at
 *
 * http://www.eclipse.org/legal/epl-v10.html
 */

package org.junit.jupiter.api.extension;

import static org.junit.platform.commons.meta.API.Usage.Experimental;

import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;

import org.junit.platform.commons.meta.API;
import org.junit.platform.commons.util.Preconditions;

/**
 * {@code ExtensionContext} encapsulates the context in which the
 * current test or container is being executed.
 *
 * 

{@link Extension Extensions} are provided an instance of * {@code ExtensionContext} to perform their work. * * @since 5.0 * @see Store * @see Namespace */ @API(Experimental) public interface ExtensionContext { /** * Get the parent extension context, if available. * * @return an {@code Optional} containing the parent; never {@code null} but * potentially empty */ Optional getParent(); /** * Get the unique ID of the current test or container. * * @return the unique ID of the test or container; never {@code null} or blank */ String getUniqueId(); /** * Get the display name for the current test or container. * *

The display name is either a default name or a custom name configured * via {@link org.junit.jupiter.api.DisplayName @DisplayName}. * *

For details on default display names consult the Javadoc for * {@link org.junit.jupiter.api.TestInfo#getDisplayName()}. * *

Note that display names are typically used for test reporting in IDEs * and build tools and may contain spaces, special characters, and even emoji. * * @return the display name of the test or container; never {@code null} or blank */ String getDisplayName(); /** * Get the set of all tags for the current test or container. * *

Tags may be declared directly on the test element or inherited * from an outer context. * * @return the set of tags for the test or container; never {@code null} but * potentially empty */ Set getTags(); /** * Get the {@link AnnotatedElement} corresponding to the current extension * context, if available. * *

For example, if the current extension context encapsulates a test * class or test method, the annotated element will be the corresponding * {@link Class} or {@link Method} reference. * *

Favor this method over more specific methods whenever the * {@code AnnotatedElement} API suits the task at hand — for example, * when looking up annotations regardless of concrete element type. * * @return an {@code Optional} containing the {@code AnnotatedElement}; * never {@code null} but potentially empty * @see #getTestClass() * @see #getTestMethod() */ Optional getElement(); /** * Get the {@link Class} associated with the current test or container, * if available. * * @return an {@code Optional} containing the class; never {@code null} but * potentially empty */ Optional> getTestClass(); /** * Get the {@link Method} associated with the current test, if available. * * @return an {@code Optional} containing the method; never {@code null} but * potentially empty */ Optional getTestMethod(); /** * Publish a map of key-value pairs to be consumed by an * {@code org.junit.platform.engine.EngineExecutionListener}. * * @param map the key-value pairs to be published; never {@code null}; * keys and values within entries in the map also must not be * {@code null} or blank */ void publishReportEntry(Map map); /** * Get the {@link Store} for the default, global {@link Namespace}. * * @return the default, global {@code Store}; never {@code null} * @see #getStore(Namespace) * @see Namespace#DEFAULT */ default Store getStore() { return getStore(Namespace.DEFAULT); } /** * Get the {@link Store} for the supplied {@link Namespace}. * * @param namespace the {@code Namespace} to get the store for; never {@code null} * @return the store in which to put and get objects for other invocations * working in the same namespace; never {@code null} */ Store getStore(Namespace namespace); /** * {@code Store} provides methods for extensions to save and retrieve data. */ interface Store { /** * Get the value that is stored under the supplied {@code key}. * *

If no value is stored in the current {@link ExtensionContext} * for the supplied {@code key}, ancestors of the context will be queried * for a value with the same {@code key} in the {@code Namespace} used * to create this store. * *

For greater type safety, consider using {@link #get(Object, Class)} * instead. * * @param key the key; never {@code null} * @return the value; potentially {@code null} * @see #get(Object, Class) */ Object get(Object key); /** * Get the value of the specified required type that is stored under * the supplied {@code key}. * *

If no value is stored in the current {@link ExtensionContext} * for the supplied {@code key}, ancestors of the context will be queried * for a value with the same {@code key} in the {@code Namespace} used * to create this store. * * @param key the key; never {@code null} * @param requiredType the required type of the value; never {@code null} * @param the value type * @return the value; potentially {@code null} * @see #get(Object) */ V get(Object key, Class requiredType); /** * Get the value that is stored under the supplied {@code key}. * *

If no value is stored in the current {@link ExtensionContext} * for the supplied {@code key}, ancestors of the context will be queried * for a value with the same {@code key} in the {@code Namespace} used * to create this store. If no value is found for the supplied {@code key}, * a new value will be computed by the {@code defaultCreator} (given * the {@code key} as input), stored, and returned. * *

For greater type safety, consider using * {@link #getOrComputeIfAbsent(Object, Function, Class)} instead. * * @param key the key; never {@code null} * @param defaultCreator the function called with the supplied {@code key} * to create a new value; never {@code null} * @param the key type * @param the value type * @return the value; potentially {@code null} * @see #getOrComputeIfAbsent(Object, Function, Class) */ Object getOrComputeIfAbsent(K key, Function defaultCreator); /** * Get the value of the specified required type that is stored under the * supplied {@code key}. * *

If no value is stored in the current {@link ExtensionContext} * for the supplied {@code key}, ancestors of the context will be queried * for a value with the same {@code key} in the {@code Namespace} used * to create this store. If no value is found for the supplied {@code key}, * a new value will be computed by the {@code defaultCreator} (given * the {@code key} as input), stored, and returned. * * @param key the key; never {@code null} * @param defaultCreator the function called with the supplied {@code key} * to create a new value; never {@code null} * @param requiredType the required type of the value; never {@code null} * @param the key type * @param the value type * @return the value; potentially {@code null} * @see #getOrComputeIfAbsent(Object, Function) */ V getOrComputeIfAbsent(K key, Function defaultCreator, Class requiredType); /** * Store a {@code value} for later retrieval under the supplied {@code key}. * *

A stored {@code value} is visible in child {@link ExtensionContext * ExtensionContexts} for the store's {@code Namespace} unless they * overwrite it. * * @param key the key under which the value should be stored; never * {@code null} * @param value the value to store; may be {@code null} */ void put(Object key, Object value); /** * Remove the value that was previously stored under the supplied {@code key}. * *

The value will only be removed in the current {@link ExtensionContext}, * not in ancestors. * *

For greater type safety, consider using {@link #remove(Object, Class)} * instead. * * @param key the key; never {@code null} * @return the previous value or {@code null} if no value was present * for the specified key * @see #remove(Object, Class) */ Object remove(Object key); /** * Remove the value of the specified required type that was previously stored * under the supplied {@code key}. * *

The value will only be removed in the current {@link ExtensionContext}, * not in ancestors. * * @param key the key; never {@code null} * @param requiredType the required type of the value; never {@code null} * @param the value type * @return the previous value or {@code null} if no value was present * for the specified key * @see #remove(Object) */ V remove(Object key, Class requiredType); } /** * A {@code Namespace} is used to provide a scope for data saved by * extensions within a {@link Store}. * *

Storing data in custom namespaces allows extensions to avoid accidentally * mixing data between extensions or across different invocations within the * lifecycle of a single extension. */ class Namespace { /** * The default, global namespace which allows access to stored data from * all extensions. */ public static final Namespace DEFAULT = Namespace.create(new Object()); /** * Create a namespace which restricts access to data to all extensions * which use the same {@code parts} for creating a namespace. * *

The order of the {@code parts} is not significant. * *

Internally the {@code parts} are compared using {@code Object.equals(Object)}. */ public static Namespace create(Object... parts) { Preconditions.notNull(parts, "There must be at least one reference object to create a namespace"); return new Namespace(parts); } private final Set parts; private Namespace(Object... parts) { this.parts = new HashSet<>(Arrays.asList(parts)); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Namespace that = (Namespace) o; return this.parts.equals(that.parts); } @Override public int hashCode() { return parts.hashCode(); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy