Here's what the JUnit 5 User Guide has to say about Dynamic Tests:
§2.17. Dynamic Tests
The standard @Test annotation in JUnit Jupiter described in Annotations is very similar to the @Test annotation in JUnit 4. Both describe methods that implement test cases. These test cases are static in the sense that they are fully specified at compile time, and their behavior cannot be changed by anything happening at runtime. Assumptions provide a basic form of dynamic behavior but are intentionally rather limited in their expressiveness.
In addition to these standard tests a completely new kind of test programming model has been introduced in JUnit Jupiter. This new kind of test is a dynamic test which is generated at runtime by a factory method that is annotated with @TestFactory.
In contrast to @Test methods, a @TestFactory method is not itself a test case but rather a factory for test cases. Thus, a dynamic test is the product of a factory. Technically speaking, a @TestFactory method must return a single DynamicNode or a Stream, Collection, Iterable, Iterator, or array of DynamicNode instances. Instantiable subclasses of DynamicNode are DynamicContainer and DynamicTest. DynamicContainer instances are composed of a display name and a list of dynamic child nodes, enabling the creation of arbitrarily nested hierarchies of dynamic nodes. DynamicTest instances will be executed lazily, enabling dynamic and even non-deterministic generation of test cases.
[...]
A DynamicTest is a test case generated at runtime. It is composed of a display name and an Executable. Executable is a @FunctionalInterface which means that the implementations of dynamic tests can be provided as lambda expressions or method references.
Dynamic Test Lifecycle
The execution lifecycle of a dynamic test is quite different than it is for a standard @Test case. Specifically, there are no lifecycle callbacks for individual dynamic tests. This means that @BeforeEach and @AfterEach methods and their corresponding extension callbacks are executed for the @TestFactory method but not for each dynamic test. In other words, if you access fields from the test instance within a lambda expression for a dynamic test, those fields will not be reset by callback methods or extensions between the execution of individual dynamic tests generated by the same @TestFactory method.
[...]
As explained, a dynamic test is generated at runtime and is represented by a DynamicTest object. This means when you have a @TestFactory method you are creating tests, not executing them. In order to support lazy execution you need to encapsulate the actual test in an object, which is done with Executable. It may help to imagine a single DynamicTest as a "normal" @Test. Say you have:
@TestFactory
DynamicTest generateDynamicTest() {
    return DynamicTest.dynamicTest(
            "2 + 2 = 4", 
            () -> assertEquals(4, 2 + 2, "the world is burning")
    );
}
As a @Test method the above would look like:
@Test
@DisplayName("2 + 2 = 4")
void testMath() {
    assertEquals(4, 2 + 2, "the world is burning");
}
Note: The two are not quite equivalent. As mentioned in the user guide, dynamic tests do not have the same lifecycle as normal @Test methods—read the guide to understand the differences.
In other words, the Executable is the body of the test method. You can think of a @TestFactory as generating a bunch of test methods at runtime (conceptually). So when you wrap your test code in an Executable you are creating a function and passing the function to the framework. This allows dynamic tests to mimic the behavior of non-dynamic tests and let's the framework execute the tests when it's ready to do so.
To answer your two additional questions you put in a comment:
- 
- By "actual code-to-be-tested" do you mean "actual code-to-be-tested-evaluation" (tests)? because i think code-to-be-tested = multiply(x,y) is invoked immediately , but it's the assertion() which waits, am I right? 
 - The wording of "code-to-be-tested" is, I now realize, ambiguous if not just misleading. Yes, I mean the test code (i.e. the code wrapped in the - Executable, such as the assertions) is what you don't want to be invoked immediately, but rather at some later time—when the test framework is ready to execute the test.
 - Note you potentially have "double the laziness" in your example due to the use of - Stream<DynamicTest>. Since a- Streamis evaluated lazily, and you don't eagerly build the- Stream(e.g. with- Stream.of), it only creates the- DynamicTestobjects as they're needed. This can be beneficial if creating the- DynamicTestis expensive because creating all the tests up front can be avoided. Whether or not JUnit Jupiter takes advantage of this, I'm not sure (haven't looked at the implementation), though I'd be surprised if they didn't.
 
- 
- And what is the point of executing-later? what is the advantage of later and not immediately? what are the method waiting for? 
 - The - DynamicTestis waiting to be passed to the framework and then waiting for the framework to execute it (and executing the- DynamicTestinvolves executing the- Executable).
 - Remember, we're dealing with a test factory here, which means you are creating the tests and not executing the tests. Executing the tests is the responsibility of the framework. If the - Executablewas executed eagerly then it'd be you executing the test instead of the framework. In effect, eager execution would hide each- DynamicTestinside the- @TestFactorymethod, preventing the framework from seeing them as individual tests; the framework has to know which test it's executing in order to give an accurate report. Plus, if eagerly executed, a test failure would prevent any remaining tests from being executed.
 
Note the example in your question could also be accomplished with a parameterized test.
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
class MultiplicationTests {
    static Stream<Integer[]> numbersProvider() {
        return Stream.of(
                new Integer[]{1, 2, 2},
                new Integer[]{5, 3, 15},
                new Integer[]{121, 4, 484}
        );
    }
    @ParameterizedTest(name = "{0} * {1} = {2}")
    @MethodSource("numbersProvider")
    void testMultiplication(int a, int b, int expectedResult) {
        assertEquals(expectedResult, a * b);
    }
}
Of course, this just seems like another way to do the same thing. So what's the difference between a @ParameterizedTest and a @TestFactory?
- A parameterized test goes through the normal lifecycle for each invocation.
- With a test factory, the entire test can be dynamically generated, not just the parameters. You could probably mimic this with a parameterized test but you'd be fighting against the design.
- With a test factory, you're literally creating tests; a parameterized test already exists, you're just providing different parameters for each invocation.
At least, that's how I understand the differences.