/*
* Copyright (c) 2006-2011 Rogério Liesenfeld
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit;
import java.lang.annotation.*;
/**
* Indicates an instance <em>field</em> or test method <em>parameter</em> whose value will be a mocked instance.
* Such fields or parameters can be of any type, except for primitive and array types.
* The declared type of the <em>mock field</em> or <em>mock parameter</em> is the <em>mocked type</em> (unless
* {@linkplain #realClassName specified otherwise}).
* For the duration of each test where such a <em>mocked type</em> is in scope, all new instances of that type, as well
* as those previously existing, will also be mocked.
* <em>Static methods</em> and <em>constructors</em> belonging to a mocked class type are mocked as well, just like
* instance methods.
* Static <em>class initializers</em> (including assignments to static fields) of a mocked class are <em>not</em>
* stubbed out by default, but they will be if {@linkplain #stubOutClassInitialization specified}.
* <p/>
* In the case of an instance field, it can be declared in a test class, in a super-class of a test class, or in an
* {@link Expectations} subclass.
* In the case of a parameter, it can only be declared in a test method.
* <p/>
* Notice that not only a concrete {@code Expectations} subclass used in specific tests can declare mock fields, but
* also any intermediate super-class in the inheritance hierarchy from {@code Expectations} to the "final" subclass.
* This can be used to define reusable {@code Expectations} subclasses, which will define one or more mock fields common
* to a given set of tests.
* <p/>
* Note also that for inner {@code Expectations} subclasses the full set of mock fields will consist of the local
* "inner" fields plus any fields declared in the test class.
* This can be used to declare mock fields that are common to all tests in the class, even though some of these tests
* may define additional mock fields in specific {@code Expectations} subclasses.
* The same applies to mock parameters declared for the test method.
* <p/>
* Therefore, there are three possible scopes for mocked types, from larger to smaller: the whole test class, the test
* method, and the expectation block inside the test method. Some tests will use only one or two of these scopes, while
* others can take advantage of all three.
* <p/>
* Usually, a mocked instance gets created and assigned to a declared mock field automatically, without the test code
* having to do anything.
* It is also possible, however, for the test itself to provide this instance, by declaring the field as {@code final}
* and assigning to it the desired instance.
* If no such instance is necessary because only static methods or constructors will be called, then this final field
* can receive the {@literal null} reference.
* Mock parameters, on the other hand, will always receive a mocked argument whenever the test method is executed by the
* test runner.
* <p/>
* For each mocked type there is at least one <em>target class for mocking</em>, which is derived from the declared type
* of the mock field or parameter, or specified through an annotation attribute.
* By default, all methods (including those which are {@code static}, {@code final}, {@code private}, {@code abstract},
* or {@code native}) and constructors in the target classes will be mocked; in addition, all static class initializers
* (if any, and including assignments to static fields) will be stubbed out.
* <p/>
* When a method or constructor is mocked, any invocations will not result in the execution of the original code, but
* only in a call back to JMockit; according to the current phase of execution for the test - <em>record</em>,
* <em>replay</em>, or <em>verify</em> - JMockit will then take the appropriate actions.
* <p/>
* The following rules are applied when deriving target classes from the mocked type:
* <ol>
* <li>The type is a concrete or <em>enum</em> class: this class and all its super-classes up to but excluding
* {@code java.lang.Object} will be the target classes for mocking.</li>
* <li>The type is an <em>interface</em> or <em>annotation</em>: a
* {@linkplain java.lang.reflect.Proxy dynamic proxy class} is created and used as the only target.
* </li>
* <li>The type is an <em>abstract class</em>: a concrete subclass is generated with mock implementations for the
* abstract methods in that class and in all of its super-classes (again, excluding {@code Object}); these super-classes
* are also targeted for mocking of non-abstract methods and constructors.</li>
* </ol>
* <a href="http://jmockit.googlecode.com/svn/trunk/www/tutorial/BehaviorBasedTesting.html#declaration">Tutorial</a>
*
* @see #methods
* @see #inverse
* @see #stubOutClassInitialization
* @see #capture
* @see #realClassName
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
public @interface Mocked
{
/**
* Same as specifying only the {@link #methods} attribute.
*/
String[] value() default {};
/**
* One or more <em>mock filters</em>.
* Given a target class for mocking, only those methods and constructors which match at least one filter will be
* mocked.
* <p/>
* If no other annotation attribute needs to be specified for a given mocked type, then for convenience the value for
* this attribute can also be specified through the default {@link #value} attribute, that is, by just supplying the
* list of mock filters without naming any annotation attribute.
* <p/>
* Each mock filter must follow the syntax <strong>{@code [nameRegex][(paramTypeName...)]}</strong>, where
* {@code nameRegex} is a {@linkplain java.util.regex.Pattern regular expression} for matching method names, and
* {@code paramTypeName} is the name of a primitive or reference parameter type (actually, any suffix of the type
* name is enough, like "String" instead of the full class name "java.lang.String").
* If {@code nameRegex} is omitted the filter matches only constructors.
* If {@code (paramTypeName...)} is omitted the filter matches methods with any parameters.
* <p/>
* If no filters are specified, then all methods and constructors declared in the target class are mocked, and all
* static initializers are stubbed out.
* <p/>
* A filter containing just the empty string matches <em>no</em> methods, no constructors, and no static initializers
* of the target class; this can be used to obtain a mocked instance where no executable code is actually mocked or
* stubbed out.
* <p/>
* The special filter {@code "<clinit>"} can be used to match the static initializers of the target class.
* If only this filter is specified then the static initializers are stubbed out and no methods or constructors are
* mocked; the opposite can be achieved by using the {@link #inverse} attribute.
*/
String[] methods() default {};
/**
* Indicates whether the mock filters are to be inverted or not.
* If inverted, only the methods and constructors matching them are <strong>not</strong> mocked.
*/
boolean inverse() default false;
/**
* Indicates whether <em>static initialization code</em> in the mocked class should be stubbed out or not.
* Static initialization includes the execution of assignments to static fields of the class and the execution of
* static initialization blocks, if any.
* (Note that {@code static final} fields initialized with <em>compile-time</em> constants are not assigned at
* runtime, remaining unaffected whether the class is stubbed out or not.)
* <p/>
* By default, static initialization code in a mocked class is <em>not</em> stubbed out.
* The JVM will only perform static initialization of a class <em>once</em>, so stubbing out the initialization code
* can have unexpected consequences.
* Static initialization will occur the first time the class is instantiated, has a static method called on it, or
* has a static field whose value is defined at runtime accessed; these are the only events which prompt the JVM to
* initialize a class.
* If the original class initialization code was stubbed out, then it will not be there to be executed at the time of
* static initialization, potentially leaving static fields {@code null} and later causing
* {@code NullPointerException}'s to occur.
*/
boolean stubOutClassInitialization() default false;
/**
* Specifies the number of new instances to <em>capture</em> during test execution, between those instances which are
* assignable to the mocked type and are created during the test.
* If applied to a non-{@code final} mock field, each captured instance will be assigned to the field, up to the
* number specified in the attribute. Otherwise (ie, when applied to a final field or a mock parameter), instances
* are still captured but not made directly available to the test.
* Note that capture can happen at any moment before the first expected invocation is recorded, or during the
* recording and replay phases.
* <p/>
* When applied to a mocked <em>class</em>, capture is not restricted to instances of that class. Instances of any
* <em>subclass</em> will also be captured. In effect, subclasses will be mocked as well, as long as they have
* already been loaded by the JVM or get loaded during test execution.
* The same applies to a mocked <em>interface</em>: instances of any implementing class will get captured.
* <p/>
* It is valid to declare two or more mock fields/parameters of the same type with a positive {@code capture} number
* for each of them, say {@code n1}, {@code n2}, etc.
* With non-final mock fields, this causes the first {@code n1} new instances to be assigned to the first field, the
* following {@code n2} new instances to the second, and so on.
*
* @see Capturing
*/
int capture() default 0;
/**
* Specify the fully qualified name of the concrete class to be considered as the mocked type when it cannot be used
* as the declared type, and the instance automatically created by JMockit for a super-type wouldn't be appropriate
* for the test.
* <p/>
* This attribute can be used with fields that are {@code final} or not.
* In the second case it can be used in conjunction with the {@link #capture} attribute, so that only the specified
* class is mocked, instead of all classes that implement/extend a given super-type.
* <p/>
* Note that this attribute can also be used when the desired concrete class is not accessible to the test (for
* example, if it's a private inner class inside the code under test).
*
* @see Expectations#newInstance(String, Class[], Object...)
*/
String realClassName() default "";
}