Full Code of ArcBees/Jukito for AI

master 280d16cf220e cached
85 files
266.5 KB
61.3k tokens
777 symbols
1 requests
Download .txt
Showing preview only (292K chars total). Download the full file or copy to clipboard to get everything.
Repository: ArcBees/Jukito
Branch: master
Commit: 280d16cf220e
Files: 85
Total size: 266.5 KB

Directory structure:
gitextract_98m20j73/

├── .gitignore
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── codequality/
│   ├── checkstyle.xml
│   ├── opensource.java.header
│   └── suppressions.xml
├── jukito/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── org/
│       │           └── jukito/
│       │               ├── All.java
│       │               ├── BindingsCollector.java
│       │               ├── Description.java
│       │               ├── EnvironmentDependentModules.java
│       │               ├── GuiceUtils.java
│       │               ├── InjectedAfterStatements.java
│       │               ├── InjectedBeforeStatements.java
│       │               ├── InjectedFrameworkMethod.java
│       │               ├── InjectedStatement.java
│       │               ├── JukitoInternal.java
│       │               ├── JukitoModule.java
│       │               ├── JukitoRunner.java
│       │               ├── MockProvider.java
│       │               ├── MockitoUsageValidator.java
│       │               ├── NamedUniqueAnnotations.java
│       │               ├── SpyImmutableInstanceProvider.java
│       │               ├── SpyProvider.java
│       │               ├── TestEagerSingleton.java
│       │               ├── TestMockSingleton.java
│       │               ├── TestModule.java
│       │               ├── TestScope.java
│       │               ├── TestSingleton.java
│       │               └── UseModules.java
│       └── test/
│           └── java/
│               └── org/
│                   └── jukito/
│                       ├── AllAnnotationTest.java
│                       ├── AllNamedAnnotationTest.java
│                       ├── AssistedInjectTest.java
│                       ├── AutoBindMocksDisabledTest.java
│                       ├── BindAnnotatedConcreteClassesTest.java
│                       ├── BindSpyInstanceTest.java
│                       ├── BindSpyTest.java
│                       ├── BindingToProviderTest.java
│                       ├── EDRunner.java
│                       ├── EnvironmentDependentComponent.java
│                       ├── ExternalSingleton.java
│                       ├── ForceMockTest.java
│                       ├── GeneralTest.java
│                       ├── InnerClassTest.java
│                       ├── InstallTest.java
│                       ├── ModuleWithProvidesMethods.java
│                       ├── NoModuleTest.java
│                       ├── OldStyleAssistedInjectTest.java
│                       ├── OneHundred.java
│                       ├── ParentClassInnerClassModuleDiscoveryTest.java
│                       ├── ParentTestClassBase.java
│                       ├── ParentTestClassTest.java
│                       ├── ProviderBindingTest.java
│                       ├── ProviderTest.java
│                       ├── ProvidesMethodTest.java
│                       ├── ReportWriterTest.java
│                       ├── RequestInjectionTest.java
│                       ├── RequestStaticInjectionTest.java
│                       ├── RespectProvidesAnnotationInModuleTest.java
│                       ├── RespectTestScopeWhenUsingAbstractModuleTest.java
│                       ├── SampleParentTestClassWithInnerTestModule.java
│                       ├── SingletonTest.java
│                       ├── SomeCoreComponent.java
│                       ├── SomeTestClass.java
│                       ├── TestTestDescriptions.java
│                       ├── TransitiveDependencyTest.java
│                       ├── UseModulesTest.java
│                       ├── Value3.java
│                       └── environmentdependent/
│                           ├── DesktopModule.java
│                           ├── EnvironmentDependentModulesTest.java
│                           ├── MobileModule.java
│                           └── TabletModule.java
├── jukito-samples/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── org/
│       │           └── jukito/
│       │               └── samples/
│       │                   ├── Car.java
│       │                   ├── DieselEngine.java
│       │                   ├── Engine.java
│       │                   ├── FordMustang.java
│       │                   ├── PetrolEngine.java
│       │                   └── modules/
│       │                       ├── DieselLineModule.java
│       │                       └── PetrolLineModule.java
│       └── test/
│           └── java/
│               └── org/
│                   └── jukito/
│                       └── samples/
│                           ├── FordMustangTest.java
│                           ├── FordMustangTest2.java
│                           └── FordMustangTest3.java
└── pom.xml

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
gwt-unitCache
www-test
target
.project
*.iml
.settings
.idea
.classpath
.gwt
bin
META-INF
.checkstyle


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing


================================================
FILE: LICENSE.md
================================================
# License

Jukito is freely distributable under the [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0.html).


================================================
FILE: README.md
================================================
![Jukito](http://i.imgur.com/rSeHAEc.png "Jukito")

### The combined power of JUnit, Guice and Mockito. Plus it sounds like a cool martial art.

-----

So you started using dependency injection because somebody told you it would make your tests simpler? But as you gaze at your deep hierarchy of test classes, "simple" is not exactly the word you think of. Plus, creating a new mock whenever you add a parameter to an injected constructor gets old very quickly.

You are not alone! And Jukito was created specifically for people like you. Read on, or [get started](https://github.com/ArcBees/Jukito/wiki) right away!

If you use [Google Guice](http://code.google.com/p/google-guice/), or if your GWT application uses [Gin](http://code.google.com/p/google-gin/), then Jukito is the perfect antidote to your unit testing headaches. Now you can write tests like this:

```java
@RunWith(JukitoRunner.class)
public class EmailSystemTest {

  @Inject EmailSystemImpl emailSystem;
  Email dummyEmail;

  @Before
  public void setupMocks(
      IncomingEmails incomingEmails,
      EmailFactory factory) {
    dummyEmail = factory.createDummy();
    when(incomingEmails.count()).thenReturn(1);
    when(incomingEmails.get(0)).thenReturn(dummyEmail);
  }

  @Test
  public void shouldFetchEmailWhenStarting(
      EmailView emailView) {
    // WHEN
    emailSystem.start();

    // THEN
    verify(emailView).addEmail(dummyEmail);
  }
}
```

That's right, Jukito lets you `@Inject` fields exactly as if your test class was injected with Guice. You can also inject parameters into your `@Test`, `@Before` and `@After` methods. Guice's just-in-time binding automatically instantiate your concrete classes, like `EmailFactory`. What about interfaces like `IncomingEmails` or `EmailView`? Jukito mocks them out automatically for you using [mockito](https://code.google.com/p/mockito/)!

Let's look at another example:

```java
@RunWith(JukitoRunner.class)
public class CalculatorTest {

  public static class Module extends JukitoModule {
    protected void configureTest() {
      bindMany(Calculator.class,
          ScientificCalculator.class,
          BusinessCalculator.class);

      bindManyInstances(AdditionExample.class, 
          new AdditionExample(1, 1, 2),
          new AdditionExample(10, 10, 20),
          new AdditionExample(18, 24, 42));
    }
  }

  @Test
  public void testAdd(@All Calculator calculator, @All AdditionExample example) {
    // WHEN
    int result = calculator.add(example.a, example.b);

    // THEN
    assertEquals(example.expected, result);
  }
}
```

As you see here, Jukito lets you define your very own test module, where you can bind classes just like a regular Guice module. It doesn't stop there, however. The `bindMany` methods let you bind different classes or instances to the same interface. Combined with the powerful `@All` annotation this lets you easily run a single test on a whole suite of test examples. The code above will run a total of six tests!

## Getting Started
[Read the wiki](https://github.com/ArcBees/Jukito/wiki) to find out everything Jukito has to offer, and [join the discussion](http://groups.google.com/group/jukito)!

## Latest Release
* 1.5

## Links
* [Jukito Custom Google Search](http://www.google.com/cse/home?cx=011138278718949652927:turyqq9pl64) - Search GWTP documentation, wiki and thread collections.
* [Jukito WebSite Source](https://github.com/ArcBees/jukito-website) - Jukito website source.
* [Jukito Google Group](https://groups.google.com/forum/?fromgroups#!forum/jukito) - Find help here.
* [Jukito Previous Repo](https://code.google.com/p/jukito/) - Previous home of Jukito.
* [GWTP](https://github.com/ArcBees/GWTP) - Find out more about GWT-Platform.

## Thanks to
[![Arcbees.com](http://i.imgur.com/HDf1qfq.png)](http://arcbees.com)

[![Atlassian](http://i.imgur.com/BKkj8Rg.png)](https://www.atlassian.com/)

[![IntelliJ](https://lh6.googleusercontent.com/--QIIJfKrjSk/UJJ6X-UohII/AAAAAAAAAVM/cOW7EjnH778/s800/banner_IDEA.png)](http://www.jetbrains.com/idea/index.html)


================================================
FILE: codequality/checkstyle.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
        "http://users.tpg.com.au/ojburn/dtds/configuration_1_3.dtd">

<module name="Checker">
    <property name="severity" value="error"/>
    <property name="localeCountry" value="CA"/>
    <property name="localeLanguage" value="en"/>

    <module name="LineLength">
        <property name="fileExtensions" value="java"/>
        <property name="max" value="120"/>
        <property name="ignorePattern" value="^(import( static)?|package) [^ ]+$"/>
    </module>

    <module name="TreeWalker">
        <module name="DeclarationOrder"/>
        <module name="EqualsHashCode"/>
        <module name="ExplicitInitialization"/>
        <module name="GenericWhitespace"/>
        <module name="MethodParamPad"/>
        <module name="MissingOverride"/>
        <module name="ModifiedControlVariable"/>
        <module name="ParameterAssignment"/>
        <module name="ParenPad"/>
        <module name="SimplifyBooleanExpression"/>
        <module name="SimplifyBooleanReturn"/>
        <module name="StringLiteralEquality"/>
        <module name="UnnecessaryParentheses"/>
        <module name="Indentation">
            <property name="basicOffset" value="4" />
            <property name="throwsIndent" value="8"/>
            <property name="arrayInitIndent" value="8"/>
            <property name="lineWrappingIndentation" value="8"/>
        </module>
        <module name="InterfaceIsType"/>
        <module name="RedundantImport"/>
        <module name="UnusedImports">
            <property name="processJavadoc" value="true"/>
        </module>
        <module name="IllegalImport"/>
        <module name="AvoidStarImport"/>
        <module name="ImportOrder">
            <property name="option" value="bottom"/>
            <property name="ordered" value="true"/>
            <property name="separated" value="true"/>
            <property name="groups" value="java,javax,org,com"/>
        </module>
        <module name="JavadocStyle">
            <property name="checkHtml" value="false"/>
            <property name="tokens" value="CLASS_DEF,CTOR_DEF,INTERFACE_DEF,METHOD_DEF,VARIABLE_DEF"/>
            <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Well formed java docs"/>
        </module>
        <module name="ParameterName"/>
        <module name="LocalFinalVariableName">
            <property name="format" value="^(\$|\$?[a-z][a-zA-Z0-9]*)$"/>
        </module>
        <module name="LocalVariableName">
            <property name="tokens" value="VARIABLE_DEF"/>
            <property name="format" value="^(\$|\$?[a-z][a-zA-Z0-9]*)$"/>
        </module>
        <module name="LeftCurly"/>
        <module name="RightCurly"/>
        <module name="NeedBraces">
            <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="make sure if has braces"/>
        </module>
        <module name="CovariantEquals"/>
        <module name="IllegalInstantiation">
            <property name="classes" value="java.lang.Boolean"/>
        </module>
        <module name="UpperEll">
            <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="checking for 4l rather than 4L"/>
        </module>
        <module name="DefaultComesLast"/>
        <module name="MultipleStringLiterals">
            <property name="ignoreStringsRegexp" value=".{0,3}"/>
        </module>
        <module name="IllegalInstantiation">
            <property name="classes" value="Boolean"/>
        </module>
        <module name="Regexp">
            <property name="format" value="[\r]?[\n][ \t]*[\r]?[\n][ \t]*[\r]?[\n][ \t]*"/>
            <property name="message" value="more than one blank line"/>
            <property name="illegalPattern" value="true"/>
            <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="more than one blank line"/>
        </module>
        <module name="Regexp">
            <property name="format" value="[\r]?[\n][ \t]*[\r]?[\n][ \t]+[}][ ]*[\n]"/>
            <property name="message" value="newline before }"/>
            <property name="illegalPattern" value="true"/>
            <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="newline before }"/>
        </module>
        <module name="Regexp">
            <property name="format" value="[^*][ \t]+[\r]?[\n]"/>
            <property name="message" value="trailing whitespace"/>
            <property name="illegalPattern" value="true"/>
            <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="trailing whitespace"/>
        </module>
        <module name="RedundantModifier"/>
        <module name="ModifierOrder"/>
        <module name="EmptyStatement"/>
        <module name="MethodName"/>
        <module name="MemberName">
            <property name="format" value="[a-z]|[a-z][a-z_0-9][A-Za-z0-9_]*|[a-z](?&lt;!f)[A-Z0-9]*"/>
        </module>
        <module name="NoWhitespaceBefore">
            <property name="allowLineBreaks" value="true"/>
            <property name="tokens" value="DOT"/>
        </module>
        <module name="NoWhitespaceAfter">
            <property name="allowLineBreaks" value="false"/>
            <property name="tokens" value="BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/>
        </module>
        <module name="WhitespaceAround">
            <property name="tokens"
                      value="COLON,NOT_EQUAL,QUESTION,DIV,DIV_ASSIGN,BXOR,BXOR_ASSIGN,MINUS,LCURLY,STAR,STAR_ASSIGN,TYPE_EXTENSION_AND,BAND,LAND,BAND_ASSIGN,MOD,MOD_ASSIGN,PLUS,PLUS_ASSIGN,LT,SL,SL_ASSIGN,LE,ASSIGN,MINUS_ASSIGN,EQUAL,GT,GE,SR,SR_ASSIGN,BSR,BSR_ASSIGN,BOR,BOR_ASSIGN,LOR,LITERAL_ASSERT,LITERAL_ASSERT,LITERAL_CATCH,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_RETURN,SLIST,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE"/>
            <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Must have spaces"/>
        </module>
        <module name="WhitespaceAfter">
            <property name="tokens" value="TYPECAST"/>
        </module>
        <module name="TypecastParenPad">
            <property name="tokens" value="RPAREN,TYPECAST"/>
        </module>
        <module name="SuppressionCommentFilter">
            <property name="offCommentFormat" value="CHECKSTYLE_OFF"/>
            <property name="onCommentFormat" value="CHECKSTYLE_ON"/>
        </module>
        <module name="SuppressionCommentFilter">
            <property name="offCommentFormat" value="CHECKSTYLE_NAMING_OFF"/>
            <property name="onCommentFormat" value="CHECKSTYLE_NAMING_ON"/>
            <property name="checkFormat" value=".*Name.*"/>
            <property name="messageFormat" value=".*name.*"/>
            <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Avoid name checking"/>
        </module>
    </module>

    <module name="Translation"/>
    <module name="NewlineAtEndOfFile">
        <property name="lineSeparator" value="lf"/>
    </module>
    <module name="FileTabCharacter">
        <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="no tabs"/>
    </module>
    <module name="RegexpSingleline">
        <property name="format" value="  [/][/][A-z]"/>
        <property name="message" value="// comments must be followed by a space and be on their own line"/>
        <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="bad // comment"/>
    </module>
    <module name="RegexpHeader">
        <property name="fileExtensions" value="java"/>
        <property name="headerFile" value="codequality/opensource.java.header"/>
    </module>
</module>


================================================
FILE: codequality/opensource.java.header
================================================
/\*\*?
 \* Copyright \d{4} ArcBees Inc\.
 \*
 \* Licensed under the Apache License, Version 2\.0 \(the "License"\); you may not
 \* use this file except in compliance with the License\. You may obtain a copy of
 \* the License at
 \*
 \* http://www\.apache\.org/licenses/LICENSE-2\.0
 \*
 \* Unless required by applicable law or agreed to in writing, software
 \* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 \* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied\. See the
 \* License for the specific language governing permissions and limitations under
 \* the License\.
 \*/


================================================
FILE: codequality/suppressions.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suppressions PUBLIC
        "-//Puppy Crawl//DTD Suppressions 1.1//EN"
        "http://users.tpg.com.au/ojburn/dtds/suppressions_1_1.dtd">

<suppressions>
    <!-- Suppress files under target -->
    <suppress checks=".*" files=".*[/\\]target[/\\].*"/>

    <!-- Suppress method naming under test -->
    <suppress checks="MethodName" files=".*[/\\]test[/\\].*"/>

    <!-- Suppress files under com/google -->
    <suppress checks=".*" files="com[/\\]google[/\\]"/>
</suppressions>


================================================
FILE: jukito/pom.xml
================================================
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.jukito</groupId>
        <artifactId>jukito-parent</artifactId>
        <version>1.6-SNAPSHOT</version>
    </parent>

    <artifactId>jukito</artifactId>
    <packaging>jar</packaging>
    <name>jukito</name>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-deploy-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-checkstyle-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-release-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>animal-sniffer-maven-plugin</artifactId>
            </plugin>

            <!-- run 'mvn javadoc:aggregate' to generate -->
            <!-- run 'mvn javadoc:aggregate -X' to debug -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
            </plugin>

            <!-- run 'mvn site' to upload -->
            <!-- run 'mvn site -X' to debug and upload. -->
            <plugin>
                <groupId>com.github.github</groupId>
                <artifactId>site-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>

        <dependency>
            <groupId>com.google.inject</groupId>
            <artifactId>guice</artifactId>
        </dependency>

        <dependency>
            <groupId>com.google.inject.extensions</groupId>
            <artifactId>guice-assistedinject</artifactId>
        </dependency>
    </dependencies>
</project>


================================================
FILE: jukito/src/main/java/org/jukito/All.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.google.inject.BindingAnnotation;

/**
 * This annotation can be used on one or more parameter of a test function.
 * The test function will be executed multiple times, one for each value bound
 * to the parameter type.
 * <p/>
 * If more than one parameter is annotated with {@literal @}{@link All} then
 * all combinations will be used. Therefore, be careful when using it on more than
 * two or three parameters as it can result in a combinatorial explosion.
 * <p/>
 * Using the additional parameter {@link #value()} a subset of all bound values
 * can be specified to be run in the test function.
 *
 * @see {@link TestModule#bindMany}
 * @see {@link TestModule#bindManyInstances}
 * @see {@link TestModule#bindManyNamed}
 * @see {@link TestModule#bindManyNamedInstances}
 */
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface All {
    String DEFAULT = "__ALL__";

    /**
     * Used in conjunction with {@link org.jukito.JukitoModule#bindManyNamed(Class, String, Class[])} and related
     * methods to retrieve all objects binded with the given name.
     */
    String value() default DEFAULT;
}


================================================
FILE: jukito/src/main/java/org/jukito/BindingsCollector.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import com.google.inject.AbstractModule;
import com.google.inject.Binding;
import com.google.inject.Key;
import com.google.inject.Scope;
import com.google.inject.spi.ConstructorBinding;
import com.google.inject.spi.ConvertedConstantBinding;
import com.google.inject.spi.DefaultBindingScopingVisitor;
import com.google.inject.spi.DefaultBindingTargetVisitor;
import com.google.inject.spi.DefaultElementVisitor;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.Element;
import com.google.inject.spi.Elements;
import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.InstanceBinding;
import com.google.inject.spi.LinkedKeyBinding;
import com.google.inject.spi.Message;
import com.google.inject.spi.PrivateElements;
import com.google.inject.spi.ProviderBinding;
import com.google.inject.spi.ProviderInstanceBinding;
import com.google.inject.spi.ProviderKeyBinding;
import com.google.inject.spi.StaticInjectionRequest;
import com.google.inject.spi.UntargettedBinding;

/**
 * Collects all the bindings from a Guice module, so that Jukito can identify missing
 * bindings and bind them to mock or instances.
 */
public class BindingsCollector {

    /**
     * Information on a binding, used by Jukito to identify provided keys and needed keys.
     */
    public static class BindingInfo {

        public Object boundInstance;
        Key<?> key;
        Key<?> boundKey;
        String scope;

        public static BindingInfo create(Binding<?> binding, Key<?> boundKey,
                Object instance) {
            BindingInfo bindingInfo = new BindingInfo();
            bindingInfo.key = binding.getKey();
            bindingInfo.boundKey = boundKey;
            bindingInfo.boundInstance = instance;
            bindingInfo.scope = binding.acceptScopingVisitor(new GuiceScopingVisitor());
            return bindingInfo;
        }

        public static BindingInfo create(Key<?> boundKey) {
            BindingInfo bindingInfo = new BindingInfo();
            bindingInfo.boundKey = boundKey;

            return bindingInfo;
        }
    }

    private final AbstractModule module;
    private final List<BindingInfo> bindingsObserved = new ArrayList<>();
    private final List<Message> messages = new ArrayList<>();

    BindingsCollector(AbstractModule module) {
        this.module = module;
    }

    public void collectBindings() {
        GuiceElementVisitor visitor = new GuiceElementVisitor();
        visitor.visitElements(Elements.getElements(module));

        // TODO report errors?
    }

    public List<BindingInfo> getBindingsObserved() {
        return bindingsObserved;
    }

    /**
     * This visitor collects all information on various guice elements.
     */
    public class GuiceElementVisitor extends DefaultElementVisitor<Void> {

        private void visitElements(List<Element> elements) {
            for (Element element : elements) {
                element.acceptVisitor(this);
            }
        }

        @Override
        public <T> Void visit(com.google.inject.Binding<T> command) {
            GuiceBindingVisitor<T> bindingVisitor = new GuiceBindingVisitor<>();
            command.acceptTargetVisitor(bindingVisitor);
            return null;
        }

        @SuppressWarnings("unchecked")
        @Override
        public Void visit(PrivateElements privateElements) {
            Set<Key<?>> exposedKeys = privateElements.getExposedKeys();
            for (Element element : privateElements.getElements()) {
                if (element instanceof Binding<?>) {
                    Binding<?> bindingElement = (Binding<?>) element;
                    if (exposedKeys.contains(bindingElement.getKey())) {
                        @SuppressWarnings("rawtypes")
                        GuicePrivateBindingVisitor bindingVisitor = new GuicePrivateBindingVisitor();
                        bindingElement.acceptTargetVisitor(bindingVisitor);
                    }
                }
            }
            return null;
        }

        @Override
        public Void visit(StaticInjectionRequest staticInjectionRequest) {
            for (InjectionPoint injectionPoint : staticInjectionRequest.getInjectionPoints()) {
                addInjectionPointDependencies(injectionPoint);
            }

            return super.visit(staticInjectionRequest);
        }

        @Override
        public Void visit(Message message) {
            messages.add(message);
            return null;
        }

        private void addInjectionPointDependencies(InjectionPoint injectionPoint) {
            // Do not consider dependencies coming from optional injections.
            if (injectionPoint.isOptional()) {
                return;
            }

            for (Dependency<?> dependency : injectionPoint.getDependencies()) {
                Key<?> key = dependency.getKey();

                bindingsObserved.add(BindingInfo.create(key));
            }
        }
    }

    /**
     * This visitor collects all information on guice bindings.
     */
    public class GuiceBindingVisitor<T> extends DefaultBindingTargetVisitor<T, Void> {

        protected Void addBindingInfo(Binding<? extends T> binding, Key<?> boundKey, Object instance) {
            bindingsObserved.add(BindingInfo.create(binding, boundKey, instance));
            return null;
        }

        private Void addBinding(Binding<? extends T> binding) {
            return addBindingInfo(binding, binding.getKey(), null);
        }

        private Void addBindingKey(Binding<? extends T> binding, Key<?> boundKey) {
            return addBindingInfo(binding, boundKey, null);
        }

        private Void addBindingInstance(Binding<? extends T> binding, Object instance) {
            return addBindingInfo(binding, null, instance);
        }

        @Override
        public Void visit(ProviderBinding<? extends T> providerBinding) {
            return addBindingKey(providerBinding, providerBinding.getProvidedKey());
        }

        @Override
        public Void visit(ProviderKeyBinding<? extends T> providerKeyBinding) {
            return addBindingKey(providerKeyBinding, providerKeyBinding.getProviderKey());
        }

        @Override
        public Void visit(ProviderInstanceBinding<? extends T> providerInstanceBinding) {
            return addBindingInstance(providerInstanceBinding,
                    providerInstanceBinding.getProviderInstance());
        }

        @Override
        public Void visit(InstanceBinding<? extends T> instanceBinding) {
            return addBindingInstance(instanceBinding, instanceBinding.getInstance());
        }

        @Override
        public Void visit(ConvertedConstantBinding<? extends T> constantBinding) {
            return addBindingInstance(constantBinding, constantBinding.getValue());
        }

        @Override
        public Void visit(UntargettedBinding<? extends T> untargettedBinding) {
            return addBinding(untargettedBinding);
        }

        @Override
        public Void visit(LinkedKeyBinding<? extends T> linkedKeyBinding) {
            return addBindingKey(linkedKeyBinding, linkedKeyBinding.getLinkedKey());
        }

        @Override
        public Void visit(ConstructorBinding<? extends T> constructorBinding) {
            return addBinding(constructorBinding);
        }
    }

    /**
     * This visitor collects the bindings for PrivateModules. Because the child
     * elements are private, the bound keys are not recorded.
     */
    public class GuicePrivateBindingVisitor<T> extends GuiceBindingVisitor<T> {

        @Override
        public Void visit(LinkedKeyBinding<? extends T> linkedKeyBinding) {
            return addBindingInfo(linkedKeyBinding, null, null);
        }
    }

    /**
     * This visitor collects all information on guice scopes associated to the bindings.
     */
    public static class GuiceScopingVisitor extends DefaultBindingScopingVisitor<String> {

        @Override
        public String visitEagerSingleton() {
            return "EagerSingleton";
        }

        @Override
        public String visitScope(Scope scope) {
            return scope.toString();
        }

        @Override
        public String visitScopeAnnotation(Class<? extends Annotation> scopeAnnotation) {
            return scopeAnnotation.getCanonicalName();
        }
    }
}


================================================
FILE: jukito/src/main/java/org/jukito/Description.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Annotation can be used for better test description (instead of camel case test method).
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Description {
    String value();
}


================================================
FILE: jukito/src/main/java/org/jukito/EnvironmentDependentModules.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.google.inject.Module;

/**
 * Annotation used for declaration of modules which are installed
 * and used separately in different applications
 * but test for it collaborators are the same and thus
 * run for against Environment Dependent Modules.
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EnvironmentDependentModules {
    Class<? extends Module>[] value();
}


================================================
FILE: jukito/src/main/java/org/jukito/GuiceUtils.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import com.google.inject.ConfigurationException;
import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.TypeLiteral;
import com.google.inject.internal.Annotations;
import com.google.inject.internal.Errors;
import com.google.inject.internal.ErrorsException;

/**
 * A number of useful static methods to manipulate Guice object. Most are
 * taken from the source code of Guice, but cannot be accessed in there.
 */
public class GuiceUtils {

    public static boolean isProvider(Key<?> key) {
        return key.getTypeLiteral().getRawType().equals(Provider.class);
    }

    @SuppressWarnings("unchecked")
    public static <T> TypeLiteral<T> getProvidedType(
            TypeLiteral<? extends Provider<? extends T>> initialProviderTypeLiteral,
            Errors errors) throws ErrorsException {

        TypeLiteral<? extends Provider<? extends T>> providerTypeLiteral = initialProviderTypeLiteral;
        while (providerTypeLiteral.getRawType() != Provider.class) {
            providerTypeLiteral = (TypeLiteral<? extends Provider<? extends T>>)
                    providerTypeLiteral.getSupertype(Provider.class);
        }

        Type providerType = providerTypeLiteral.getType();

        // If the Provider has no type parameter (raw Provider)...
        if (!(providerType instanceof ParameterizedType)) {
            throw errors.cannotInjectRawProvider().toException();
        }

        Type entryType = ((ParameterizedType) providerType).getActualTypeArguments()[0];
        return (TypeLiteral<T>) TypeLiteral.get(entryType);
    }

    public static <T> Key<T> getProvidedKey(Key<Provider<T>> key,
            Errors errors) throws ErrorsException {
        TypeLiteral<T> providedType = getProvidedType(key.getTypeLiteral(), errors);

        Key<T> providedKey;
        if (key.getAnnotation() == null) {
            providedKey = (Key<T>) Key.get(providedType);
        } else {
            providedKey = (Key<T>) Key.get(providedType, key.getAnnotation());
        }
        return providedKey;
    }

    @SuppressWarnings("unchecked")
    public static <T> Key<T> ensureProvidedKey(Key<T> key, Errors errors) {
        try {
            return isProvider(key) ? getProvidedKey((Key<Provider<T>>) key, errors) : key;
        } catch (ConfigurationException e) {
            errors.merge(e.getErrorMessages());
        } catch (ErrorsException e) {
            errors.merge(e.getErrors());
        }
        return null;
    }

    public static List<Key<?>> getMethodKeys(Method method, Errors errors) {
        Annotation allParameterAnnotations[][] = method.getParameterAnnotations();
        List<Key<?>> result = new ArrayList<Key<?>>(allParameterAnnotations.length);
        Iterator<Annotation[]> annotationsIterator = Arrays.asList(allParameterAnnotations).iterator();
        TypeLiteral<?> type = TypeLiteral.get(method.getDeclaringClass());
        for (TypeLiteral<?> parameterType : type.getParameterTypes(method)) {
            try {
                Annotation[] parameterAnnotations = annotationsIterator.next();
                result.add(Annotations.getKey(parameterType, method, parameterAnnotations, errors));
            } catch (ConfigurationException e) {
                errors.merge(e.getErrorMessages());
            } catch (ErrorsException e) {
                errors.merge(e.getErrors());
            }
        }
        return result;
    }
}


================================================
FILE: jukito/src/main/java/org/jukito/InjectedAfterStatements.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.util.ArrayList;
import java.util.List;

import org.junit.internal.runners.model.MultipleFailureException;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;

import com.google.inject.Injector;

/**
 * A {@link Statement} invoking a list of methods with parameters by filling-in
 * these parameters with injected instances. The methods are called after the
 * provided {@code prev} {@link Statement}.
 */
public class InjectedAfterStatements extends Statement {

    private final Statement prev;
    private final List<Statement> afters;

    public InjectedAfterStatements(Statement prev, List<FrameworkMethod> afters,
            Object target, Injector injector) {
        this.prev = prev;
        this.afters = new ArrayList<Statement>(afters.size());
        for (FrameworkMethod method : afters) {
            this.afters.add(new InjectedStatement(method, target, injector));
        }
    }

    @Override
    public void evaluate() throws Throwable {
        List<Throwable> errors = new ArrayList<Throwable>();
        errors.clear();
        try {
            prev.evaluate();
        } catch (Throwable e) {
            errors.add(e);
        } finally {
            for (Statement after : afters) {
                try {
                    after.evaluate();
                } catch (Throwable e) {
                    errors.add(e);
                }
            }
        }
        if (!errors.isEmpty()) {
            throw new MultipleFailureException(errors);
        }
    }
}


================================================
FILE: jukito/src/main/java/org/jukito/InjectedBeforeStatements.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.util.ArrayList;
import java.util.List;

import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;

import com.google.inject.Injector;

/**
 * A {@link Statement} invoking a list of methods with parameters by filling-in
 * these parameters with injected instances. The methods are called before the
 * provided {@code next} {@link Statement}.
 */
public class InjectedBeforeStatements extends Statement {

    private final Statement next;
    private final List<Statement> befores;

    public InjectedBeforeStatements(Statement next, List<FrameworkMethod> befores,
            Object target, Injector injector) {
        this.next = next;
        this.befores = new ArrayList<Statement>(befores.size());
        for (FrameworkMethod method : befores) {
            this.befores.add(new InjectedStatement(method, target, injector));
        }
    }

    @Override
    public void evaluate() throws Throwable {
        for (Statement before : befores) {
            before.evaluate();
        }
        next.evaluate();
    }
}


================================================
FILE: jukito/src/main/java/org/jukito/InjectedFrameworkMethod.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.lang.reflect.Method;
import java.util.List;

import org.junit.runners.model.FrameworkMethod;

import com.google.inject.Binding;

/**
 * This class is an extension of {@link FrameworkMethod} that makes it possible to specify
 * which {@link Binding} to use for parameters marked with {@literal @}{@link All}.
 */
public class InjectedFrameworkMethod extends FrameworkMethod {

    private final List<Binding<?>> bindingsToUseForParameters;

    public InjectedFrameworkMethod(Method method) {
        super(method);
        bindingsToUseForParameters = null;
    }

    public InjectedFrameworkMethod(Method method, List<Binding<?>> bindingsToUseForParameters) {
        super(method);
        this.bindingsToUseForParameters = bindingsToUseForParameters;
    }

    public List<Binding<?>> getBindingsToUseForParameters() {
        return bindingsToUseForParameters;
    }
}


================================================
FILE: jukito/src/main/java/org/jukito/InjectedStatement.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;

import com.google.inject.Binding;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.internal.Errors;

/**
 * A {@link Statement} invoking a method with parameters by filling-in these
 * parameters with injected instances.
 */
class InjectedStatement extends Statement {

    private final FrameworkMethod method;
    private final Object test;
    private final Injector injector;

    InjectedStatement(FrameworkMethod method, Object test, Injector injector) {
        this.method = method;
        this.test = test;
        this.injector = injector;
    }

    @Override
    public void evaluate() throws Throwable {
        Method javaMethod = method.getMethod();
        Injector methodInjector = injector;

        UseModules useModules = javaMethod.getAnnotation(UseModules.class);
        if (useModules != null) {
            Class<? extends Module>[] moduleClasses = useModules.value();
            final Module[] modules = new Module[moduleClasses.length];
            for (int i = 0; i < modules.length; i++) {
                modules[i] = moduleClasses[i].newInstance();
            }
            TestModule jukitoModule;
            if (useModules.autoBindMocks()) {
                jukitoModule = new JukitoModule() {
                    @Override
                    protected void configureTest() {
                        for (Module m : modules) {
                            install(m);
                        }
                    }
                };
            } else {
                jukitoModule = new TestModule() {
                    @Override
                    protected void configureTest() {
                        for (Module m : modules) {
                            install(m);
                        }
                    }
                };
            }
            methodInjector = Guice.createInjector(jukitoModule);
        }

        Errors errors = new Errors(javaMethod);
        List<Key<?>> keys = GuiceUtils.getMethodKeys(javaMethod, errors);
        errors.throwConfigurationExceptionIfErrorsExist();

        Iterator<Binding<?>> bindingIter;
        if (InjectedFrameworkMethod.class.isAssignableFrom(method.getClass())) {
            bindingIter = ((InjectedFrameworkMethod) method).getBindingsToUseForParameters().iterator();
        } else {
            bindingIter = new ArrayList<Binding<?>>().iterator();
        }

        List<Object> injectedParameters = new ArrayList<Object>();
        for (Key<?> key : keys) {
            if (!All.class.equals(key.getAnnotationType())) {
                injectedParameters.add(methodInjector.getInstance(key));
            } else {
                if (!bindingIter.hasNext()) {
                    throw new AssertionError("Expected more bindings to fill @All parameters.");
                }
                injectedParameters.add(methodInjector.getInstance(bindingIter.next().getKey()));
            }
        }

        method.invokeExplosively(test, injectedParameters.toArray());
    }
}


================================================
FILE: jukito/src/main/java/org/jukito/JukitoInternal.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.google.inject.BindingAnnotation;

/**
 * An internal binding annotation used when binding {@link SpyProvider}.
 * See {@link TestModule#bindSpy(Class)}.
 */
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@interface JukitoInternal {
}


================================================
FILE: jukito/src/main/java/org/jukito/JukitoModule.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import org.jukito.BindingsCollector.BindingInfo;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.google.inject.ConfigurationException;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.MembersInjector;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.Stage;
import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.internal.Errors;
import com.google.inject.internal.ProviderMethod;
import com.google.inject.internal.ProviderMethodsModule;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.HasDependencies;
import com.google.inject.spi.InjectionPoint;

/**
 * A guice {@link com.google.inject.Module Module} with a bit of syntactic sugar
 * to bind within typical test scopes. Depends on mockito. This module
 * automatically mocks any interface or abstract class dependency for which a
 * binding is not explicitly provided. Any concrete class for which a binding is
 * not explicitly provided is bound as a {@link TestScope#SINGLETON}.
 * <p/>
 * Depends on Mockito.
 */
public abstract class JukitoModule extends TestModule {

    protected List<BindingInfo> bindingsObserved = Collections.emptyList();

    private final Set<Class<?>> forceMock = new HashSet<>();
    private final Set<Class<?>> dontForceMock = new HashSet<>();
    private final List<Key<?>> keysNeedingTransitiveDependencies = new ArrayList<>();
    private final Map<Class<?>, Object> primitiveTypes = new HashMap<>();

    public JukitoModule() {
        primitiveTypes.put(String.class, "");
        primitiveTypes.put(Integer.class, 0);
        primitiveTypes.put(Long.class, 0L);
        primitiveTypes.put(Boolean.class, false);
        primitiveTypes.put(Double.class, 0.0);
        primitiveTypes.put(Float.class, 0.0f);
        primitiveTypes.put(Short.class, (short) 0);
        primitiveTypes.put(Character.class, '\0');
        primitiveTypes.put(Byte.class, (byte) 0);
        primitiveTypes.put(Class.class, Object.class);
    }

    /**
     * Attach this {@link JukitoModule} to a list of the bindings that were
     * observed by a preliminary run of {@link BindingsCollector}.
     *
     * @param bindingsObserved The observed bindings.
     */
    public void setBindingsObserved(List<BindingInfo> bindingsObserved) {
        this.bindingsObserved = bindingsObserved;
    }

    /**
     * By default, only abstract classes, interfaces and classes annotated with
     * {@link TestMockSingleton} are automatically mocked. Use {@link #forceMock}
     * to indicate that all concrete classes derived from the a specific type
     * will be mocked in {@link TestMockSingleton} scope.
     *
     * @param klass The {@link Class} or interface for which all subclasses will be mocked.
     */
    protected void forceMock(Class<?> klass) {
        forceMock.add(klass);
    }

    @Override
    @SuppressWarnings({"unchecked", "rawtypes"})
    public final void configure() {
        bindScopes();
        configureTest();

        Set<Key<?>> keysObserved = new HashSet<>(bindingsObserved.size());
        Set<Key<?>> keysNeeded = new HashSet<>(bindingsObserved.size());

        for (BindingInfo bindingInfo : bindingsObserved) {
            if (bindingInfo.key != null) {
                keysObserved.add(bindingInfo.key);
            }
            if (bindingInfo.boundKey != null) {
                keysNeeded.add(bindingInfo.boundKey);
            }
            if (bindingInfo.boundInstance != null &&
                    bindingInfo.boundInstance instanceof HasDependencies) {
                HasDependencies hasDependencies = (HasDependencies) bindingInfo.boundInstance;
                for (Dependency<?> dependency : hasDependencies.getDependencies()) {
                    keysNeeded.add(dependency.getKey());
                }
            }
        }

        // registering keys build via @Provides methods in this module in the keysObserved set.
        ProviderMethodsModule providerMethodsModule = (ProviderMethodsModule)
                ProviderMethodsModule.forModule(this);

        List<ProviderMethod<?>> providerMethodList = providerMethodsModule.getProviderMethods(binder());
        for (ProviderMethod<?> providerMethod : providerMethodList) {
            keysObserved.add(providerMethod.getKey());
        }

        // Make sure needed keys from Guice bindings are bound as mock or to instances
        // (but not as test singletons)
        for (Key<?> keyNeeded : keysNeeded) {
            addNeededKey(keysObserved, keysNeeded, keyNeeded, false);
            keysNeedingTransitiveDependencies.add(keyNeeded);
        }

        // Preempt JIT binding by looking through the test class and any parent class
        // looking for methods annotated with @Test, @Before, or @After.
        // Concrete classes bound in this way are bound in @TestSingleton.
        Class<?> currentClass = testClass;
        while (currentClass != null) {
            for (Method method : currentClass.getDeclaredMethods()) {
                if (method.isAnnotationPresent(Test.class)
                        || method.isAnnotationPresent(Before.class)
                        || method.isAnnotationPresent(After.class)) {

                    Errors errors = new Errors(method);
                    List<Key<?>> keys = GuiceUtils.getMethodKeys(method, errors);

                    for (Key<?> key : keys) {
                        // Skip keys annotated with @All
                        if (!All.class.equals(key.getAnnotationType())) {
                            Key<?> keyNeeded = GuiceUtils.ensureProvidedKey(key, errors);
                            addNeededKey(keysObserved, keysNeeded, keyNeeded, true);
                        }
                    }
                    errors.throwConfigurationExceptionIfErrorsExist();
                }
            }
            currentClass = currentClass.getSuperclass();
        }

        // Preempt JIT binding by looking through the test class looking for
        // fields and methods annotated with @Inject.
        // Concrete classes bound in this way are bound in @TestSingleton.
        if (testClass != null) {
            Set<InjectionPoint> injectionPoints = InjectionPoint.forInstanceMethodsAndFields(testClass);

            for (InjectionPoint injectionPoint : injectionPoints) {
                Errors errors = new Errors(injectionPoint);
                List<Dependency<?>> dependencies = injectionPoint.getDependencies();
                for (Dependency<?> dependency : dependencies) {
                    Key<?> keyNeeded = GuiceUtils.ensureProvidedKey(dependency.getKey(),
                            errors);
                    addNeededKey(keysObserved, keysNeeded, keyNeeded, true);
                }
                errors.throwConfigurationExceptionIfErrorsExist();
            }
        }

        // Recursively add the dependencies of all the bindings observed. Warning, we can't use for each here
        // since it would result into concurrency issues.
        for (int i = 0; i < keysNeedingTransitiveDependencies.size(); ++i) {
            addDependencies(keysNeedingTransitiveDependencies.get(i), keysObserved, keysNeeded);
        }

        // Bind all keys needed but not observed as mocks.
        for (Key<?> key : keysNeeded) {
            Class<?> rawType = key.getTypeLiteral().getRawType();
            if (!keysObserved.contains(key) && !isCoreGuiceType(rawType)
                    && !isAssistedInjection(key)) {
                Object primitiveInstance = getDummyInstanceOfPrimitiveType(rawType);
                if (primitiveInstance == null) {
                    if (rawType != Provider.class && !isInnerClass(rawType)) {
                        bind(key).toProvider(new MockProvider(rawType)).in(TestScope.SINGLETON);
                    }
                } else {
                    bindKeyToInstance(key, primitiveInstance);
                }
            }
        }
    }

    private boolean isInnerClass(Class<?> rawType) {
        return rawType.isMemberClass() && !Modifier.isStatic(rawType.getModifiers());
    }

    @SuppressWarnings("unchecked")
    private <T> void bindKeyToInstance(Key<T> key, Object primitiveInstance) {
        bind(key).toInstance((T) primitiveInstance);
    }

    private void addNeededKey(Set<Key<?>> keysObserved, Set<Key<?>> keysNeeded,
            Key<?> keyNeeded, boolean asTestSingleton) {
        keysNeeded.add(keyNeeded);
        bindIfConcrete(keysObserved, keyNeeded, asTestSingleton);
    }

    private <T> void bindIfConcrete(Set<Key<?>> keysObserved,
            Key<T> key, boolean asTestSingleton) {
        TypeLiteral<?> typeToBind = key.getTypeLiteral();
        Class<?> rawType = typeToBind.getRawType();
        if (!keysObserved.contains(key) && canBeInjected(typeToBind)
                && !shouldForceMock(rawType) && !isAssistedInjection(key)) {

            // If an @Singleton annotation is present, force the bind as TestSingleton
            if (asTestSingleton ||
                    rawType.getAnnotation(Singleton.class) != null) {
                bind(key).in(TestScope.SINGLETON);
            } else {
                bind(key);
            }
            keysObserved.add(key);
            keysNeedingTransitiveDependencies.add(key);
        }
    }

    private boolean canBeInjected(TypeLiteral<?> type) {
        Class<?> rawType = type.getRawType();
        if (isPrimitive(rawType) || isCoreGuiceType(rawType) || !isInstantiable(rawType)) {
            return false;
        }
        try {
            InjectionPoint.forConstructorOf(type);
            return true;
        } catch (ConfigurationException e) {
            return false;
        }
    }

    private boolean isAssistedInjection(Key<?> key) {
        return key.getAnnotationType() != null
                && Assisted.class.isAssignableFrom(key.getAnnotationType());
    }

    private boolean shouldForceMock(Class<?> klass) {
        if (dontForceMock.contains(klass)) {
            return false;
        }
        if (forceMock.contains(klass)) {
            return true;
        }
        // The forceMock set contains all the base classes the user wants
        // to force mock, check id the specified klass is a subclass of one of
        // these.
        // Update forceMock or dontForceMock based on the result to speed-up
        // future look-ups.
        boolean result = false;
        for (Class<?> classToMock : forceMock) {
            if (classToMock.isAssignableFrom(klass)) {
                result = true;
                break;
            }
        }

        if (result) {
            forceMock.add(klass);
        } else {
            dontForceMock.add(klass);
        }

        return result;
    }

    private boolean isInstantiable(Class<?> klass) {
        return !klass.isInterface() && !Modifier.isAbstract(klass.getModifiers());
    }

    private boolean isPrimitive(Class<?> klass) {
        return getDummyInstanceOfPrimitiveType(klass) != null;
    }

    private Object getDummyInstanceOfPrimitiveType(Class<?> klass) {
        Object instance = primitiveTypes.get(klass);
        if (instance == null && Enum.class.isAssignableFrom(klass)) {
            // Safe to ignore exception, Guice will fail with a reasonable error
            // if the Enum is empty.
            try {
                instance = ((Object[]) klass.getMethod("values").invoke(null))[0];
            } catch (Exception ignored) {
            }
        }
        return instance;
    }

    private boolean isCoreGuiceType(Class<?> klass) {
        return TypeLiteral.class.isAssignableFrom(klass)
                || Injector.class.isAssignableFrom(klass)
                || Logger.class.isAssignableFrom(klass)
                || Stage.class.isAssignableFrom(klass)
                || MembersInjector.class.isAssignableFrom(klass);
    }

    private <T> void addDependencies(Key<T> key, Set<Key<?>> keysObserved,
            Set<Key<?>> keysNeeded) {
        TypeLiteral<T> type = key.getTypeLiteral();
        if (!canBeInjected(type)) {
            return;
        }
        addInjectionPointDependencies(InjectionPoint.forConstructorOf(type),
                keysObserved, keysNeeded);
        Set<InjectionPoint> methodsAndFieldsInjectionPoints =
                InjectionPoint.forInstanceMethodsAndFields(type);
        for (InjectionPoint injectionPoint : methodsAndFieldsInjectionPoints) {
            addInjectionPointDependencies(injectionPoint, keysObserved, keysNeeded);
        }
    }

    private void addInjectionPointDependencies(InjectionPoint injectionPoint,
            Set<Key<?>> keysObserved, Set<Key<?>> keysNeeded) {
        // Do not consider dependencies coming from optional injections
        if (injectionPoint.isOptional()) {
            return;
        }
        for (Dependency<?> dependency : injectionPoint.getDependencies()) {
            Key<?> key = dependency.getKey();
            addKeyDependency(key, keysObserved, keysNeeded);
        }
    }

    private void addKeyDependency(Key<?> key, Set<Key<?>> keysObserved,
            Set<Key<?>> keysNeeded) {
        Key<?> newKey = key;
        if (Provider.class.equals(key.getTypeLiteral().getRawType())) {
            Type providedType = (
                    (ParameterizedType) key.getTypeLiteral().getType()).getActualTypeArguments()[0];
            if (key.getAnnotation() != null) {
                newKey = Key.get(providedType, key.getAnnotation());
            } else if (key.getAnnotationType() != null) {
                newKey = Key.get(providedType, key.getAnnotationType());
            } else {
                newKey = Key.get(providedType);
            }
        }
        addNeededKey(keysObserved, keysNeeded, newKey, true);
    }

    /**
     * Override and return the {@link Writer} you want to use to report the tree of test objects,and whether they
     * were mocked, spied, automatically instantiated, or explicitly bound. Mostly useful for
     * debugging.
     *
     * @return The {@link Writer}, if {@code null} no report will be output.
     */
    public Writer getReportWriter() {
        return null;
    }

    /**
     * Outputs the report, see {@link #setReportWriter(Writer)}. Will not output anything if the
     * {@code reportWriter} is {@code null}. Do not call directly, it will be called by
     * {@link JukitoRunner}. To obtain a report, override {@link #getReportWriter()}.
     */
    public void printReport(List<BindingInfo> allBindings) {
        Writer reportWriter = getReportWriter();
        if (reportWriter == null) {
            return;
        }

        try {
            reportWriter.append("*** EXPLICIT BINDINGS ***\n");
            Set<Key<?>> reportedKeys = outputBindings(reportWriter, bindingsObserved,
                    Collections.<Key<?>>emptySet());
            reportWriter.append('\n');
            reportWriter.append("*** AUTOMATIC BINDINGS ***\n");
            outputBindings(reportWriter, allBindings, reportedKeys);
            reportWriter.append('\n');
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param reportWriter The {@link Writer} to use to output the report.
     * @param bindings     The bindings to report.
     * @param keysToSkip   The keys that should not be reported.
     * @return All the keys that were reported.
     * @throws IOException If something goes wrong when writing.
     */
    private Set<Key<?>> outputBindings(Writer reportWriter, List<BindingInfo> bindings,
            Set<Key<?>> keysToSkip) throws IOException {

        Set<Key<?>> reportedKeys = new HashSet<>(bindings.size());
        for (BindingInfo bindingInfo : bindings) {
            if (keysToSkip.contains(bindingInfo.key)) {
                continue;
            }
            reportedKeys.add(bindingInfo.key);
            reportWriter.append("  ");
            reportWriter.append(bindingInfo.key.toString());
            reportWriter.append(" --> ");
            if (bindingInfo.boundKey != null) {
                if (bindingInfo.key == bindingInfo.boundKey) {
                    reportWriter.append("Bound directly");
                } else {
                    reportWriter.append(bindingInfo.boundKey.toString());
                }
            } else if (bindingInfo.boundInstance != null) {
                reportWriter.append("Instance of ").append(bindingInfo.boundInstance.getClass().getCanonicalName());
            } else {
                reportWriter.append("NOTHING!?");
            }
            reportWriter.append(" ### ");
            if (bindingInfo.scope == null) {
                reportWriter.append("No scope");
            } else {
                reportWriter.append("In scope ");
                reportWriter.append(bindingInfo.scope);
            }
            reportWriter.append('\n');
        }
        return reportedKeys;
    }
}


================================================
FILE: jukito/src/main/java/org/jukito/JukitoRunner.java
================================================
/*
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;

import com.google.inject.Binding;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.Scope;
import com.google.inject.TypeLiteral;
import com.google.inject.internal.Errors;
import com.google.inject.spi.DefaultBindingScopingVisitor;

/*
 * This class implements the mockito runner but allows Guice dependency
 * injection. To setup the guice environment, the test class can have an inner
 * static class deriving from {@link TestModule}. This last class will let you bind
 * {@link TestSingleton} and {@link TestEagerSingleton} and the runner will make sure these
 * singletons are reset at every invocation of a test case.
 *
 *
 * Most of the code here is inspired from: <a href=
 * "http://cowwoc.blogspot.com/2008/10/integrating-google-guice-into-junit4.html"
 * > http://cowwoc.blogspot.com/2008/10/integrating-google-guice-into-junit4.
 * html</a>
 *
 * Depends on Mockito.
 */
public class JukitoRunner extends BlockJUnit4ClassRunner {

    private Injector injector;

    public JukitoRunner(Class<?> klass) throws InitializationError,
            InvocationTargetException, InstantiationException, IllegalAccessException {
        super(klass);
        ensureInjector();
    }

    public JukitoRunner(Class<?> klass, Injector injector) throws InitializationError,
            InvocationTargetException, InstantiationException, IllegalAccessException {
        // refactor needed here cos ensureInjector is run without reason here.
        super(klass);
        this.injector = injector;
    }

    /**
     * Creates an injector from a test module.
     * Override this to use something like Netflix Governator.
     *
     * @param testModule the test module
     * @return a newly created injector
     */
    protected Injector createInjector(TestModule testModule) {
        return Guice.createInjector(testModule);
    }

    private void ensureInjector()
            throws InstantiationException, IllegalAccessException {
        if (injector != null) {
            return;
        }
        Class<?> testClass = getTestClass().getJavaClass();
        TestModule testModule = getTestModule(testClass);
        testModule.setTestClass(testClass);

        JukitoModule jukitoModule = null; // Only non-null if it's a JukitoModule
        if (testModule instanceof JukitoModule) {
            jukitoModule = (JukitoModule) testModule;

            // Create a module just for the purpose of collecting bindings
            TestModule testModuleForCollection = getTestModule(testClass);
            BindingsCollector collector = new BindingsCollector(testModuleForCollection);
            collector.collectBindings();
            jukitoModule.setBindingsObserved(collector.getBindingsObserved());
        }
        injector = this.createInjector(testModule);
        if (jukitoModule != null && jukitoModule.getReportWriter() != null) {
            // An output report is desired
            BindingsCollector collector = new BindingsCollector(jukitoModule);
            collector.collectBindings();
            jukitoModule.printReport(collector.getBindingsObserved());
        }
    }

    private TestModule getTestModule(Class<?> testClass) throws InstantiationException, IllegalAccessException {
        Set<Class<? extends Module>> useModuleClasses = getUseModuleClasses(testClass);
        boolean autoBindMocks = getAutoBindMocksValue(testClass);
        if (!useModuleClasses.isEmpty()) {
            return createJukitoModule(useModuleClasses, autoBindMocks);
        }

        TestModule testModule = getInnerClassModule(testClass);
        if (testModule != null) {
            return testModule;
        }

        if (autoBindMocks) {
            return new JukitoModule() {
                @Override
                protected void configureTest() {
                }
            };
        } else {
            return new TestModule() {
                @Override
                protected void configureTest() {
                }
            };
        }
    }

    /**
     * Gets Guice modules registered with {@link UseModules} from test class and all super classes.
     *
     * @param testClass the test class running
     * @return set of Guice modules
     */
    private Set<Class<? extends Module>> getUseModuleClasses(Class<?> testClass) {
        Class<?> currentClass = testClass;
        Set<Class<? extends Module>> modules = new HashSet<>();
        while (currentClass != null) {
            UseModules useModules = currentClass.getAnnotation(UseModules.class);
            if (useModules != null) {
                Collections.addAll(modules, useModules.value());
            }
            currentClass = currentClass.getSuperclass();
        }
        return modules;
    }

    private TestModule getInnerClassModule(Class<?> testClass)
            throws InstantiationException, IllegalAccessException {
        Class<?> currentClass = testClass;
        while (currentClass != null) {
            for (Class<?> innerClass : currentClass.getDeclaredClasses()) {
                if (TestModule.class.isAssignableFrom(innerClass)) {
                    return (TestModule) innerClass.newInstance();
                }
            }
            currentClass = currentClass.getSuperclass();
        }
        return null;
    }

    private boolean getAutoBindMocksValue(Class<?> testClass) {
        boolean autoBindMocks = true;
        Class<?> currentClass = testClass;
        while (currentClass != null) {
            UseModules useModules = currentClass.getAnnotation(UseModules.class);
            if (useModules != null) {
                autoBindMocks = useModules.autoBindMocks();
                break;
            }
            currentClass = currentClass.getSuperclass();
        }
        return autoBindMocks;
    }

    private TestModule createJukitoModule(final Iterable<Class<? extends Module>> moduleClasses,
            boolean autoBindMocks) {
        if (autoBindMocks) {
            return new JukitoModule() {
                @Override
                protected void configureTest() {
                    for (Class<? extends Module> mClass : moduleClasses) {
                        try {
                            install(mClass.newInstance());
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            };
        } else {
            return new TestModule() {
                @Override
                protected void configureTest() {
                    for (Class<? extends Module> mClass : moduleClasses) {
                        try {
                            install(mClass.newInstance());
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            };
        }
    }

    @Override
    public void run(RunNotifier notifier) {
        // add listener that validates framework usage at the end of each test
        notifier.addListener(new MockitoUsageValidator(notifier));
        super.run(notifier);
    }

    @Override
    protected Object createTest() throws Exception {
        TestScope.clear();
        instantiateEagerTestSingletons();
        return injector.getInstance(getTestClass().getJavaClass());
    }

    @Override
    protected Statement methodInvoker(FrameworkMethod method, Object test) {
        return new InjectedStatement(method, test, injector);
    }

    @Override
    protected Statement withBefores(FrameworkMethod method, Object target,
            Statement statement) {
        try {
            ensureInjector();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        List<FrameworkMethod> befores = getTestClass().getAnnotatedMethods(
                Before.class);
        return befores.isEmpty() ? statement : new InjectedBeforeStatements(statement,
                befores, target, injector);
    }

    @Override
    protected Statement withAfters(FrameworkMethod method, Object target,
            Statement statement) {
        try {
            ensureInjector();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        List<FrameworkMethod> afters = getTestClass().getAnnotatedMethods(
                After.class);
        return afters.isEmpty() ? statement : new InjectedAfterStatements(statement,
                afters, target, injector);
    }

    @Override
    protected List<FrameworkMethod> computeTestMethods() {
        try {
            ensureInjector();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        List<FrameworkMethod> testMethods = getTestClass().getAnnotatedMethods(Test.class);
        List<FrameworkMethod> result = new ArrayList<>(testMethods.size());
        for (FrameworkMethod method : testMethods) {
            Method javaMethod = method.getMethod();
            Errors errors = new Errors(javaMethod);
            List<Key<?>> keys = GuiceUtils.getMethodKeys(javaMethod, errors);
            errors.throwConfigurationExceptionIfErrorsExist();

            List<List<Binding<?>>> bindingsToUseForParameters = new ArrayList<>();
            for (Key<?> key : keys) {
                if (All.class.equals(key.getAnnotationType())) {
                    All allAnnotation = (All) key.getAnnotation();
                    TypeLiteral<?> typeLiteral = key.getTypeLiteral();
                    List<Binding<?>> bindings = getBindingsForParameterWithAllAnnotation(allAnnotation, typeLiteral);
                    bindingsToUseForParameters.add(bindings);
                }
            }
            // Add an injected method for every combination of binding
            addAllBindingAssignations(bindingsToUseForParameters, 0,
                    new ArrayList<Binding<?>>(bindingsToUseForParameters.size()),
                    javaMethod, result);
        }
        return result;
    }

    @Override
    protected String testName(FrameworkMethod method) {
        org.jukito.Description annotation = method.getMethod().getAnnotation(org.jukito.Description.class);
        if (annotation != null) {
            return annotation.value();
        } else {
            return super.testName(method);
        }
    }

    /**
     * Computes a list of all bindings which match a {@link All} annotation.
     *
     * @param allAnnotation the annotation to match
     * @param typeLiteral   the type of the bindings.
     * @return the computed list.
     */
    private List<Binding<?>> getBindingsForParameterWithAllAnnotation(All allAnnotation, TypeLiteral<?> typeLiteral) {
        List<Binding<?>> result = new ArrayList<>();
        String bindingName = allAnnotation.value();
        if (All.DEFAULT.equals(bindingName)) {
            // If the annotation is with the default name bind all bindings
            result.addAll(injector.findBindingsByType(typeLiteral));
        } else {
            // Else bind only those bindings which have a key with the same name
            for (Binding<?> binding : injector.findBindingsByType(typeLiteral)) {
                if (NamedUniqueAnnotations.matches(bindingName, binding.getKey().getAnnotation())) {
                    result.add(binding);
                }
            }
        }
        return result;
    }

    /**
     * This method looks at all possible way to assign the bindings in
     * {@code bindingsToUseForParameters}, starting at index {@code index}.
     * If {@code index} is larger than the number of elements in {@code bindingsToUseForParameters}
     * then the {@code currentAssignation} with {@javaMethod} is added to {@code result}.
     *
     * @param result
     * @param javaMethod
     * @param bindingsToUseForParameters
     * @param index
     * @param currentAssignation
     */
    private void addAllBindingAssignations(
            List<List<Binding<?>>> bindingsToUseForParameters, int index,
            List<Binding<?>> currentAssignation,
            Method javaMethod, List<FrameworkMethod> result) {

        if (index >= bindingsToUseForParameters.size()) {
            List<Binding<?>> assignation = new ArrayList<>(currentAssignation.size());
            assignation.addAll(currentAssignation);
            result.add(new InjectedFrameworkMethod(javaMethod, assignation));
            return;
        }

        for (Binding<?> binding : bindingsToUseForParameters.get(index)) {
            if (binding.getKey().getAnnotation() == null) {
                // As TestModule.bindMany() annotates the bindings, the un-annotated bindings are typically unwanted
                // mocks automatically bound by Jukito.
                continue;
            }

            currentAssignation.add(binding);
            if (currentAssignation.size() != index + 1) {
                throw new AssertionError("Size of currentAssignation list is wrong.");
            }
            addAllBindingAssignations(bindingsToUseForParameters, index + 1,
                    currentAssignation,
                    javaMethod, result);
            currentAssignation.remove(index);
        }
    }

    private void instantiateEagerTestSingletons() {
        DefaultBindingScopingVisitor<Boolean> isEagerTestScopeSingleton =
                new DefaultBindingScopingVisitor<Boolean>() {
                    public Boolean visitScope(Scope scope) {
                        return scope == TestScope.EAGER_SINGLETON;
                    }
                };
        for (Binding<?> binding : injector.getBindings().values()) {
            boolean instantiate = false;
            if (binding != null) {
                Boolean result = binding.acceptScopingVisitor(isEagerTestScopeSingleton);
                if (result != null && result) {
                    instantiate = true;
                }
            }
            if (instantiate) {
                binding.getProvider().get();
            }
        }
    }

    /**
     * Adds to {@code errors} for each method annotated with {@code @Test},
     * {@code @Before}, or {@code @After} that is not a public, void instance
     * method with no arguments.
     */
    @Override
    protected void validateInstanceMethods(List<Throwable> errors) {
        validatePublicVoidMethods(After.class, false, errors);
        validatePublicVoidMethods(Before.class, false, errors);
        validateTestMethods(errors);

        if (computeTestMethods().size() == 0) {
            errors.add(new Exception("No runnable methods"));
        }
    }

    /**
     * Adds to {@code errors} for each method annotated with {@code @Test}that
     * is not a public, void instance method with no arguments.
     */
    @Override
    protected void validateTestMethods(List<Throwable> errors) {
        validatePublicVoidMethods(Test.class, false, errors);
    }

    /**
     * Adds to {@code errors} if any method in this class is annotated with
     * the provided {@code annotation}, but:
     * <ul>
     * <li>is not public, or
     * <li>returns something other than void, or
     * <li>is static (given {@code isStatic is false}), or
     * <li>is not static (given {@code isStatic is true}).
     */
    private void validatePublicVoidMethods(Class<? extends Annotation> annotation,
            boolean isStatic, List<Throwable> errors) {
        List<FrameworkMethod> methods = getTestClass().getAnnotatedMethods(annotation);

        for (FrameworkMethod eachTestMethod : methods) {
            eachTestMethod.validatePublicVoid(isStatic, errors);
        }
    }

    /**
     * Access the Guice injector.
     *
     * @return The Guice {@link Injector}.
     */
    protected Injector getInjector() {
        return injector;
    }
}


================================================
FILE: jukito/src/main/java/org/jukito/MockProvider.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import com.google.inject.Provider;

import static org.mockito.Mockito.mock;

/**
 * For use in test cases where an {@link Provider} is required to provide an
 * object and the test case needs to provide a mock of the object.
 * <p/>
 * A new object is returned each the the provider is invoked, unless the object
 * is bound as a {@link TestScope#SINGLETON} or {@link TestScope#EAGER_SINGLETON}.
 * <p/>
 * Depends on Mockito.
 *
 * @param <T> The class to provide.
 */
public class MockProvider<T> implements Provider<T> {

    private final Class<T> classToProvide;

    /**
     * Construct a {@link Provider} that will return mocked objects of the specified types.
     *
     * @param classToProvide The {@link Class} of the mock object to provide.
     */
    public MockProvider(Class<T> classToProvide) {
        this.classToProvide = classToProvide;
    }

    @Override
    public T get() {
        return mock(classToProvide);
    }
}


================================================
FILE: jukito/src/main/java/org/jukito/MockitoUsageValidator.java
================================================
/*
 * Copyright 2017 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;
import org.mockito.Mockito;

public class MockitoUsageValidator extends RunListener {
    private final RunNotifier notifier;

    public MockitoUsageValidator(RunNotifier notifier) {
        this.notifier = notifier;
    }

    @Override
    public void testFinished(org.junit.runner.Description description) throws Exception {
        super.testFinished(description);

        try {
            Mockito.validateMockitoUsage();
        } catch (Throwable t) {
            notifier.fireTestFailure(new Failure(description, t));
        }
    }
}


================================================
FILE: jukito/src/main/java/org/jukito/NamedUniqueAnnotations.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.util.concurrent.atomic.AtomicInteger;

import com.google.inject.BindingAnnotation;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Factory for unique annotations with a name. Based on {@link com.google.inject.internal.UniqueAnnotations}.
 */
class NamedUniqueAnnotations {
    private static final AtomicInteger nextUniqueValue = new AtomicInteger(1);

    /**
     * Returns if a NamedUniqueAnnotations matches a binding name.
     *
     * @param bindingName the name to match.
     * @param annotation  the annotation to match the name to.
     * @return if the annotation matches the bindingName.
     */
    public static boolean matches(String bindingName, java.lang.annotation.Annotation annotation) {
        if (annotation instanceof Internal) {
            return ((Internal) annotation).name().equals(bindingName);
        }
        return false;
    }

    /**
     * Returns an annotation instance that is not equal to any other annotation
     * instances, for use in creating distinct {@link com.google.inject.Key}s.
     *
     * @param name name to group multiple annotations. Each annotation is still unique even if it belongs to a group.
     */
    public static Annotation create(String name) {
        int unique = nextUniqueValue.getAndIncrement();
        String nonNullName = name == null ? All.DEFAULT : name;
        return new InternalImpl(unique, nonNullName);
    }

    @Retention(RUNTIME)
    @BindingAnnotation
    private @interface Internal {
        String name();

        int value();
    }

    private static class InternalImpl implements Internal {
        private final int value;
        private final String name;

        InternalImpl(int value, String name) {
            this.value = value;
            this.name = name;
        }

        public int value() {
            return value;
        }

        public String name() {
            return name;
        }

        public Class<? extends Annotation> annotationType() {
            return Internal.class;
        }

        @Override
        public String toString() {
            return "@" + Internal.class.getName() + "(name=" + name + ", value=" + value + ")";
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o instanceof Internal) {
                Internal other = (Internal) o;
                return value() == other.value() && name().equals(other.name());
            }
            return false;
        }

        @Override
        public int hashCode() {
            return (127 * name.hashCode()) ^ value;
        }
    }
}


================================================
FILE: jukito/src/main/java/org/jukito/SpyImmutableInstanceProvider.java
================================================
/**
 * Copyright 2014 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import org.mockito.Mockito;

import com.google.inject.Provider;

/**
 * For use in classes where you want to create a spied instance, as in
 * {@link com.google.inject.binder.LinkedBindingBuilder#toInstance(T))},
 * except the instance is a spy.
 * <p/>
 * A new spy is returned each time this {@link Provider} is invoked, wrapping the
 * exact same instance class.
 * <p/>
 * <b>Important:</b> Spied object needs to be Immutable
 */
class SpyImmutableInstanceProvider<T> implements Provider<T> {
    private final T instance;

    /**
     * Create a new {@link Provider} instance for use in creating spies of
     * concrete instances.
     * <p/>
     * This instance should be immutable; if it is not, you risk polluting your tests as the underlying instance is the
     * same (even though it uses a different spy wrapper).
     *
     * @param instance The instance to be returned.
     */
    SpyImmutableInstanceProvider(T instance) {
        this.instance = instance;
    }

    /**
     * Create a new spy of your bound instance.
     */
    @Override
    public T get() {
        return Mockito.spy(instance);
    }
}


================================================
FILE: jukito/src/main/java/org/jukito/SpyProvider.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.util.Collections;
import java.util.Set;

import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.HasDependencies;

import static org.mockito.Mockito.spy;

/**
 * For use in test cases where an {@link Provider} is required to provide an
 * object and the test case needs to provide a spy of the object.
 * <p/>
 * A new object is returned each the the provider is invoked, unless the object
 * is bound as a {@link TestScope#SINGLETON} or {@link TestScope#EAGER_SINGLETON}.
 * <p/>
 * Depends on Mockito.
 *
 * @param <T> The class to provide.
 */
class SpyProvider<T> implements Provider<T>, HasDependencies {

    private final Provider<T> rawProvider;
    private final Set<Dependency<?>> dependencies;

    /**
     * Construct a {@link Provider} that will return spied instances of objects
     * of the specified types. You should not call this directly, instead use
     * {@link TestModule#bindSpy(Class)} or {@link TestModule#bindSpy(com.google.inject.TypeLiteral)}.
     *
     * @param rawProvider The test class, running with {@link JukitoRunner}.
     * @param relayingKey The key of the binding used to relay to the real class. This should usually be the key of a
     *                    {code toConstructor} binding. Internally, Jukito uses the {@link JukitoInternal} annotation to
     *                    distinguish this binding.
     */
    SpyProvider(Provider<T> rawProvider, Key<T> relayingKey) {
        this.rawProvider = rawProvider;
        dependencies = Collections.<Dependency<?>>singleton(Dependency.get(relayingKey));
    }

    @Override
    public T get() {
        return spy(rawProvider.get());
    }

    @Override
    public Set<Dependency<?>> getDependencies() {
        return dependencies;
    }
}


================================================
FILE: jukito/src/main/java/org/jukito/TestEagerSingleton.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.google.inject.ScopeAnnotation;

/**
 * This annotation can be used on any classes that should be bound
 * within the {@link TestScope#EAGER_SINGLETON} scope. It is meant to be
 * used on inner static classes of the test class or its parents
 * and shouldn't be used on top-level classes.
 */
@ScopeAnnotation
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface TestEagerSingleton {
}


================================================
FILE: jukito/src/main/java/org/jukito/TestMockSingleton.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * This annotation can be used on any classes that should be bound as
 * a mock within the {@link TestScope#SINGLETON} scope. It is meant to be
 * used on inner static classes of the test class or its parents
 * and shouldn't be used on top-level classes.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TestMockSingleton {
}


================================================
FILE: jukito/src/main/java/org/jukito/TestModule.java
================================================
/**
 * Copyright 2014 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.lang.reflect.Constructor;

import com.google.inject.AbstractModule;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.binder.LinkedBindingBuilder;
import com.google.inject.binder.ScopedBindingBuilder;
import com.google.inject.name.Names;
import com.google.inject.spi.InjectionPoint;

/**
 * A guice {@link com.google.inject.Module Module} with a bit of syntactic sugar to bind within
 * typical test scopes. Depends on mockito.
 * <p/>
 * Depends on Mockito.
 */
public abstract class TestModule extends AbstractModule {

    protected Class<?> testClass;

    /**
     * Attach the {@link TestModule} to a given test class.
     *
     * @param testClass The test class to attach to this {@link TestModule}.
     */
    public void setTestClass(Class<?> testClass) {
        this.testClass = testClass;
    }

    @Override
    public void configure() {
        bindScopes();
        configureTest();
    }

    protected void bindScopes() {
        bindScope(TestSingleton.class, TestScope.SINGLETON);
        bindScope(TestEagerSingleton.class, TestScope.EAGER_SINGLETON);
    }

    /**
     * Configures a test {@link com.google.inject.Module Module} via the exposed methods.
     */
    protected abstract void configureTest();

    /**
     * Binds an interface to a mocked version of itself. You will usually want to bind this in the
     * {@link TestSingleton} scope.
     *
     * @param <T>   The type of the interface to bind
     * @param klass The class to bind
     * @return A {@link ScopedBindingBuilder}.
     */
    protected <T> ScopedBindingBuilder bindMock(Class<T> klass) {
        return bindNewMockProvider(Key.get(klass));
    }

    /**
     * Binds an interface annotated with a {@link com.google.inject.name.Named @Named} to a
     * mocked version of itself. You will usually want to bind this in the
     * {@link TestSingleton} scope.
     *
     * @param <T>         The type of the interface to bind, a parameterized type
     * @param typeLiteral The {@link TypeLiteral} corresponding to the parameterized type to bind.
     * @return A {@link ScopedBindingBuilder}.
     */
    protected <T> ScopedBindingBuilder bindMock(
            TypeLiteral<T> typeLiteral) {
        return bindNewMockProvider(Key.get(typeLiteral));
    }

    /**
     * Binds a concrete object type so that spies of instances are returned
     * instead of instances themselves. You will usually want to bind this in the
     * {@link TestSingleton} scope.
     *
     * @param <T>   The type of the interface to bind
     * @param klass The class to bind
     * @return A {@link ScopedBindingBuilder}.
     */
    protected <T> ScopedBindingBuilder bindSpy(Class<T> klass) {
        return bindNewSpyProvider(Key.get(klass));
    }

    /**
     * Binds a concrete object type so that spies of instances are returned
     * instead of instances themselves. You will usually want to bind this in the
     * {@link TestSingleton} scope.
     *
     * @param <T>         The type of the interface to bind, a parameterized type
     * @param typeLiteral The {@link TypeLiteral} corresponding to the parameterized type to bind.
     * @return A {@link ScopedBindingBuilder}.
     */
    protected <T> ScopedBindingBuilder bindSpy(
            TypeLiteral<T> typeLiteral) {
        return bindNewSpyProvider(Key.get(typeLiteral));
    }

    /**
     * Binds a concrete instance so that spies of this instance are returned
     * instead of the object itself. Each spy is an independent spy but the
     * underlying instance will be the same, so if the object is mutable,
     * your tests can be polluted!
     * <p/>
     * You will usually want to bind this in the {@link TestSingleton} scope.
     *
     * @param <T>      The type of the interface to bind
     * @param klass    The class to bind
     * @param instance The instance to bind this class to.
     * @return A {@link ScopedBindingBuilder}.
     */
    protected <T> ScopedBindingBuilder bindSpy(Class<T> klass, T instance) {
        return bindNewSpyImmutableInstanceProvider(Key.get(klass), instance);
    }

    /**
     * Binds a concrete instance so that spies of this instance are returned
     * instead of the object itself. Each spy is an independent spy but the
     * underlying instance will be the same, so if the object is mutable,
     * your tests can be polluted!
     * <p/>
     * You will usually want to bind this in the
     * {@link TestSingleton} scope.
     *
     * @param <T>         The type of the interface to bind, a parameterized type
     * @param typeLiteral The {@link TypeLiteral} corresponding to the parameterized type to bind.
     * @param instance    The instance to bind this class to.
     * @return A {@link ScopedBindingBuilder}.
     */
    protected <T> ScopedBindingBuilder bindSpy(
            TypeLiteral<T> typeLiteral, T instance) {
        return bindNewSpyImmutableInstanceProvider(Key.get(typeLiteral), instance);
    }

    /**
     * Binds an interface annotated with a {@link com.google.inject.name.Named @Named} to a
     * mocked version of itself. You will usually want to bind this in the
     * {@link TestSingleton} scope.
     *
     * @param <T>   The type of the interface to bind
     * @param klass The class to bind
     * @param name  The name used with the {@link com.google.inject.name.Named @Named} annotation.
     * @return A {@link ScopedBindingBuilder}.
     */
    protected <T> ScopedBindingBuilder bindNamedMock(Class<T> klass, String name) {
        return bindNewMockProvider(Key.get(klass, Names.named(name)));
    }

    /**
     * Binds an interface annotated with a {@link com.google.inject.name.Named @Named} to a
     * mocked version of itself. You will usually want to bind this in the
     * {@link TestSingleton} scope.
     *
     * @param <T>         The type of the interface to bind
     * @param typeLiteral The {@link TypeLiteral} corresponding to the parameterized type to bind.
     * @param name        The name used with the {@link com.google.inject.name.Named @Named} annotation.
     * @return A {@link ScopedBindingBuilder}.
     */
    protected <T> ScopedBindingBuilder bindNamedMock(TypeLiteral<T> typeLiteral,
            String name) {
        return bindNewMockProvider(Key.get(typeLiteral, Names.named(name)));
    }

    /**
     * Binds a concrete object type annotated with a
     * {@link com.google.inject.name.Named @Named} so that spies of instances are returned
     * instead of instances themselves. You will usually want to bind this in the
     * {@link TestSingleton} scope.
     *
     * @param <T>   The type of the interface to bind
     * @param klass The class to bind
     * @param name  The name used with the {@link com.google.inject.name.Named @Named} annotation.
     * @return A {@link ScopedBindingBuilder}.
     */
    protected <T> ScopedBindingBuilder bindNamedSpy(Class<T> klass, String name) {
        return bindNewSpyProvider(Key.get(klass, Names.named(name)));
    }

    /**
     * Binds  a concrete object type annotated with a
     * {@link com.google.inject.name.Named @Named} so that spies of instances are returned
     * instead of instances themselves. You will usually want to bind this in the
     * {@link TestSingleton} scope.
     *
     * @param <T>         The type of the interface to bind
     * @param typeLiteral The {@link TypeLiteral} corresponding to the parameterized type to bind.
     * @param name        The name used with the {@link com.google.inject.name.Named @Named} annotation.
     * @return A {@link ScopedBindingBuilder}.
     */
    protected <T> ScopedBindingBuilder bindNamedSpy(TypeLiteral<T> typeLiteral,
            String name) {
        return bindNewSpyProvider(Key.get(typeLiteral, Names.named(name)));
    }

    /**
     * Binds a concrete instance annotated with {@link com.google.inject.name.Named @Named} so that spies of this
     * instance are returned instead of the object itself. Each spy is an independent spy but the underlying instance
     * will be the same, so if the object is mutable, your tests can be polluted!
     * <p/>
     * You will usually want to bind this in the {@link TestSingleton} scope.
     *
     * @param <T>      The type of the interface to bind
     * @param klass    The class to bind
     * @param instance The instance to bind this class to.
     * @param name     The name used with the {@link com.google.inject.name.Named @Named} annotation.
     * @return A {@link ScopedBindingBuilder}.
     */
    protected <T> ScopedBindingBuilder bindNamedSpy(Class<T> klass, T instance,
            String name) {
        return bindNewSpyImmutableInstanceProvider(Key.get(klass, Names.named(name)), instance);
    }

    /**
     * Binds a concrete instance annotated with {@link com.google.inject.name.Named @Named} so that spies of this
     * instance are returned instead of the object itself. Each spy is an independent spy but the underlying instance
     * will be the same, so if the object is mutable, your tests can be polluted!
     * <p/>
     * You will usually want to bind this in the {@link TestSingleton} scope.
     *
     * @param <T>         The type of the interface to bind
     * @param typeLiteral The {@link TypeLiteral} corresponding to the parameterized type to bind.
     * @param instance    The instance to bind this class to.
     * @param name        The name used with the {@link com.google.inject.name.Named @Named} annotation.
     * @return A {@link ScopedBindingBuilder}.
     */
    protected <T> ScopedBindingBuilder bindNamedSpy(TypeLiteral<T> typeLiteral,
            T instance, String name) {
        return bindNewSpyImmutableInstanceProvider(Key.get(typeLiteral, Names.named(name)), instance);
    }

    @SuppressWarnings("unchecked")
    private <T> ScopedBindingBuilder bindNewMockProvider(Key<T> key) {
        return bind(key).toProvider(
                new MockProvider<T>((Class<T>) key.getTypeLiteral().getRawType()));
    }

    @SuppressWarnings("unchecked")
    private <T> ScopedBindingBuilder bindNewSpyProvider(Key<T> key) {
        TypeLiteral<T> type = key.getTypeLiteral();
        InjectionPoint constructorInjectionPoint = InjectionPoint.forConstructorOf(type);
        Key<T> relayingKey = Key.get(type, JukitoInternal.class);
        bind(relayingKey).toConstructor((Constructor<T>) constructorInjectionPoint.getMember());
        return bind(key).toProvider(new SpyProvider<T>(getProvider(relayingKey), relayingKey));
    }

    private <T> ScopedBindingBuilder bindNewSpyImmutableInstanceProvider(Key<T> key, T instance) {
        return bind(key).toProvider(new SpyImmutableInstanceProvider<T>(instance));
    }

    /**
     * This method binds many different instances to the same class or interface. Use this only
     * if the instances are totally stateless. That is, they are immutable and have
     * no mutable dependencies (e.g. a {@link String} or a simple POJO). For more
     * complex classes use {@link #bindMany}.
     * <p/>
     * The specified {@link Class} will be bound to all the different instances, each
     * binding using a different unique annotation.
     * <p/>
     * This method is useful when combined with the {@literal @}{@link All} annotation.
     *
     * @param clazz     The {@link Class} to which the instances will be bound.
     * @param instances All the instances to bind.
     * @see {@link All}
     */
    protected <T, V extends T> void bindManyInstances(Class<T> clazz, V... instances) {
        bindManyNamedInstances(clazz, All.DEFAULT, instances);
    }

    /**
     * This method binds many different instances to the same class or interface. Use this only
     * if the instances are totally stateless. That is, they are immutable and have
     * no mutable dependencies (e.g. a {@link String} or a simple POJO). For more
     * complex classes use {@link #bindMany}.
     * <p/>
     * The specified {@link Class} will be bound to all the different instances, each
     * binding using a different unique but named annotation.
     * <p/>
     * This method is useful when combined with the {@literal @}{@link All} annotation with
     * a name parameter.
     *
     * @param clazz     The {@link Class} to which the instances will be bound.
     * @param name      The name to which to bind the instances.
     * @param instances All the instances to bind.
     * @see {@link All}
     */
    protected <T, V extends T> void bindManyNamedInstances(Class<T> clazz, String name, V... instances) {
        for (V instance : instances) {
            bind(clazz).annotatedWith(NamedUniqueAnnotations.create(name)).toInstance(instance);
        }
    }

    /**
     * This method binds many different instances to the same type literal. Use this only
     * if the instances are totally stateless. That is, they are immutable and have
     * no mutable dependencies (e.g. a {@link String} or a simple POJO). For more
     * complex classes use {@link #bindMany}.
     * <p/>
     * The specified {@link TypeLiteral} will be bound to all the different instances, each
     * binding using a different unique annotation.
     * <p/>
     * This method is useful when combined with the {@literal @}{@link All} annotation.
     *
     * @param type      The {@link TypeLiteral} to which the instances will be bound.
     * @param instances All the instances to bind.
     * @see {@link All}
     */
    protected <T, V extends T> void bindManyInstances(TypeLiteral<T> type, V... instances) {
        bindManyNamedInstances(type, All.DEFAULT, instances);
    }

    /**
     * This method binds many different instances to the same class or interface. Use this only
     * if the instances are totally stateless. That is, they are immutable and have
     * no mutable dependencies (e.g. a {@link String} or a simple POJO). For more
     * complex classes use {@link #bindMany}.
     * <p/>
     * The specified {@link Class} will be bound to all the different instances, each
     * binding using a different unique but named annotation.
     * <p/>
     * This method is useful when combined with the {@literal @}{@link All} annotation with
     * a name.
     *
     * @param type      The {@link Class} to which the instances will be bound.
     * @param name      The name to which to bind the instances.
     * @param instances All the instances to bind.
     * @see {@link All}
     */
    protected <T, V extends T> void bindManyNamedInstances(TypeLiteral<T> type, String name, V... instances) {
        for (V instance : instances) {
            bind(type).annotatedWith(NamedUniqueAnnotations.create(name)).toInstance(instance);
        }
    }

    /**
     * This method binds many different classes to the same interface. All the
     * classes will be bound within the {@link TestScope#SINGLETON} scope.
     * <p/>
     * This method is useful when combined with the {@literal @}{@link All} annotation.
     *
     * @param clazz        The {@link Class} to which the instances will be bound.
     * @param boundClasses All the classes to bind.
     * @see {@link All}
     */
    protected <T> void bindMany(Class<T> clazz, Class<? extends T>... boundClasses) {
        bindManyNamed(clazz, All.DEFAULT, boundClasses);
    }

    /**
     * This method binds many different type literals to the same type literal. All the
     * classes will be bound within the {@link TestScope#SINGLETON} scope.
     * <p/>
     * This method is useful when combined with the {@literal @}{@link All} annotation with
     * a name.
     *
     * @param clazz        The {@link Class} to which the instances will be bound.
     * @param name         The name to which to bind the instances.
     * @param boundClasses All the types to bind.
     * @see {@link All}
     */
    protected <T> void bindManyNamed(Class<T> clazz, String name, Class<? extends T>... boundClasses) {
        for (Class<? extends T> boundClass : boundClasses) {
            bind(clazz).annotatedWith(NamedUniqueAnnotations.create(name)).to(boundClass).in(TestScope.SINGLETON);
        }
    }

    /**
     * This method binds many different type literals to the same type literal. All the
     * classes will be bound within the {@link TestScope#SINGLETON} scope.
     * <p/>
     * This method is useful when combined with the {@literal @}{@link All} annotation.
     *
     * @param type       The {@link Class} to which the instances will be bound.
     * @param boundTypes All the types to bind.
     * @see {@link All}
     */
    protected <T> void bindMany(TypeLiteral<T> type, TypeLiteral<? extends T>... boundTypes) {
        bindManyNamed(type, All.DEFAULT, boundTypes);
    }

    /**
     * This method binds many different type literals to the same type literal. All the
     * classes will be bound within the {@link TestScope#SINGLETON} scope.
     * <p/>
     * This method is useful when combined with the {@literal @}{@link All} annotation with
     * a name.
     *
     * @param type       The {@link Class} to which the instances will be bound.
     * @param name       The name to which to bind the instances.
     * @param boundTypes All the types to bind.
     * @see {@link All}
     */
    protected <T> void bindManyNamed(TypeLiteral<T> type, String name,
            TypeLiteral<? extends T>... boundTypes) {
        for (TypeLiteral<? extends T> boundType : boundTypes) {
            bind(type).annotatedWith(NamedUniqueAnnotations.create(name)).to(boundType).in(TestScope.SINGLETON);
        }
    }

    /**
     * Binds an interface annotated with a {@link com.google.inject.name.Named @Named}.
     *
     * @param <T>   The type of the interface to bind
     * @param klass The class to bind
     * @param name  The name used with the {@link com.google.inject.name.Named @Named} annotation.
     * @return A {@link ScopedBindingBuilder}.
     */
    protected <T> LinkedBindingBuilder<T> bindNamed(Class<T> klass, String name) {
        return bind(klass).annotatedWith(Names.named(name));
    }

    /**
     * Binds an interface annotated with a {@link com.google.inject.name.Named @Named}.
     *
     * @param <T>         The type of the interface to bind
     * @param typeLiteral The {@link TypeLiteral} corresponding to the parameterized type to bind.
     * @param name        The name used with the {@link com.google.inject.name.Named @Named} annotation.
     * @return A {@link ScopedBindingBuilder}.
     */
    protected <T> LinkedBindingBuilder<T> bindNamed(TypeLiteral<T> typeLiteral,
            String name) {
        return bind(typeLiteral).annotatedWith(Names.named(name));
    }
}


================================================
FILE: jukito/src/main/java/org/jukito/TestScope.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.util.HashMap;
import java.util.Map;

import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.Scope;

/**
 * Container of the {@link #SINGLETON} and {@link #EAGER_SINGLETON} scopes for
 * test cases running with the {@link JukitoRunner}. Depends on mockito.
 * <p/>
 * Depends on Mockito.
 */
public class TestScope {

    private static class Singleton implements Scope {
        private final String simpleName;

        private final Map<Key<?>, Object> backingMap = new HashMap<Key<?>, Object>();

        private Singleton(String simpleName) {
            this.simpleName = simpleName;
        }

        public void clear() {
            backingMap.clear();
        }

        @Override
        public <T> Provider<T> scope(final Key<T> key, final Provider<T> unscoped) {
            return new Provider<T>() {
                @SuppressWarnings("unchecked")
                public T get() {

                    Object o = backingMap.get(key);

                    if (o == null) {
                        o = unscoped.get();
                        backingMap.put(key, o);
                    }
                    return (T) o;
                }
            };
        }

        public String toString() {
            return simpleName;
        }
    }

    /**
     * Test-scoped singletons are typically used in test cases for objects that
     * correspond to singletons in the application. Your JUnit test case must use
     * {@link JukitoRunner} on its {@code @RunWith} annotation so that
     * test-scoped singletons are reset before every test case.
     * <p/>
     * If you want your singleton to be instantiated automatically with each new
     * test, use {@link #EAGER_SINGLETON}.
     */
    public static final Singleton SINGLETON = new Singleton("TestSingleton");

    /**
     * Eager test-scoped singleton are similar to test-scoped {@link #SINGLETON}
     * but they get instantiated automatically with each new test.
     */
    public static final Singleton EAGER_SINGLETON = new Singleton("EagerTestSingleton");

    /**
     * Clears all the instances of test-scoped singletons. After this method is
     * called, any "singleton" bound to this scope that had already been created
     * will be created again next time it gets injected.
     */
    public static void clear() {
        SINGLETON.clear();
        EAGER_SINGLETON.clear();
    }
}


================================================
FILE: jukito/src/main/java/org/jukito/TestSingleton.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.google.inject.ScopeAnnotation;

/**
 * This annotation can be used on any classes that should be bound
 * within the {@link TestScope#SINGLETON} scope. It is meant to be
 * used on inner static classes ofx the test class or its parents
 * and shouldn't be used on top-level classes.
 */
@ScopeAnnotation
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface TestSingleton {
}


================================================
FILE: jukito/src/main/java/org/jukito/UseModules.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.google.inject.Module;

/**
 * This annotation can be used on a test class together with
 * {@code @RunWith(JukitoRunner.class)} to use the bindings contained
 * in the specified modules for the test.
 * <p/>
 * Example:
 * <pre>
 * {@literal @}RunWith(JukitoRunner.class)
 * {@literal @}UseModules({ FooModule.class, BarModule.class}
 * public class MyTest {
 *   {@literal @}Test
 *   public void someTest(TypeBoundInFooModule a, TypeBoundInBarModule b) {
 *   }
 * }</pre>
 *
 * The example is equivalent to the following <i>inner static module</i>
 * approach.
 * <pre>
 * {@literal @}RunWith(JukitoRunner.class)
 * public class MyTest {
 *   static class Module extends JukitoModule {
 *     {@literal @}Override
 *     protected void configureTest() {
 *       install(new FooModule());
 *       install(new BarModule());
 *     }
 *   }
 *   // Test methods
 * }</pre>
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface UseModules {

    Class<? extends Module>[] value();

    boolean autoBindMocks() default true;
}


================================================
FILE: jukito/src/test/java/org/jukito/AllAnnotationTest.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.util.ArrayList;
import java.util.List;

import org.junit.AfterClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

/**
 * Test that methods with some parameters annotated with {@literal @}{@link org.jukito.All} behave correctly.
 */
@RunWith(JukitoRunner.class)
public class AllAnnotationTest {

    /**
     * Guice test module.
     */
    static class Module extends JukitoModule {
        @SuppressWarnings("unchecked")
        @Override
        protected void configureTest() {
            bindManyInstances(String.class, "A", "B");
            bindManyInstances(TestDataInstance.class, new TestDataInstance("A"),
                    new TestDataInstance("B"));
            bindMany(TestData.class, TestDataA.class, TestDataB.class);
            bindMany(Node.class, NodeA.class);
        }
    }

    interface TestData {
        String getData();
    }

    static class TestDataA implements TestData {
        public String getData() {
            return "A";
        }
    }

    static class TestDataB implements TestData {
        public String getData() {
            return "B";
        }
    }

    static class TestDataInstance {
        private final String data;

        TestDataInstance(String data) {
            this.data = data;
        }

        public String getData() {
            return data;
        }
    }

    interface Node {
    }

    static class NodeA implements Node {
    }

    /**
     * This class keeps track of what happens in all the tests run in this
     * class. It's used to make sure all expected tests are called.
     */
    private static class Bookkeeper {
        static List<String> stringsProcessed = new ArrayList<String>();
        static List<String> dataProcessed = new ArrayList<String>();
        static List<String> dataInstanceProcessed = new ArrayList<String>();
    }

    @Test
    public void testAllWithInstance(@All String string1, @All String string2) {
        Bookkeeper.stringsProcessed.add(string1 + string2);
    }

    @Test
    public void testAllWithClass(@All TestData data1, @All TestData data2) {
        Bookkeeper.dataProcessed.add(data1.getData() + data2.getData());
    }

    @Test
    public void testAllWithClassInstance(@All TestDataInstance data1, @All TestDataInstance data2) {
        Bookkeeper.dataInstanceProcessed.add(data1.getData() + data2.getData());
    }

    @AfterClass
    public static void checkBookkeeper() {
        assertTrue(Bookkeeper.stringsProcessed.contains("AA"));
        assertTrue(Bookkeeper.stringsProcessed.contains("AB"));
        assertTrue(Bookkeeper.stringsProcessed.contains("BA"));
        assertTrue(Bookkeeper.stringsProcessed.contains("BB"));
        assertEquals(4, Bookkeeper.stringsProcessed.size());

        assertTrue(Bookkeeper.dataProcessed.contains("AA"));
        assertTrue(Bookkeeper.dataProcessed.contains("AB"));
        assertTrue(Bookkeeper.dataProcessed.contains("BA"));
        assertTrue(Bookkeeper.dataProcessed.contains("BB"));
        assertEquals(4, Bookkeeper.dataProcessed.size());

        assertTrue(Bookkeeper.dataInstanceProcessed.contains("AA"));
        assertTrue(Bookkeeper.dataInstanceProcessed.contains("AB"));
        assertTrue(Bookkeeper.dataInstanceProcessed.contains("BA"));
        assertTrue(Bookkeeper.dataInstanceProcessed.contains("BB"));
        assertEquals(4, Bookkeeper.dataInstanceProcessed.size());
    }

    @Test
    public void testAllDoesNotIncludeMock(@All Node node, Node neighbour) {
        assertFalse(Mockito.mockingDetails(node).isMock());
    }
}


================================================
FILE: jukito/src/test/java/org/jukito/AllNamedAnnotationTest.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.util.ArrayList;
import java.util.List;

import org.junit.AfterClass;
import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

/**
 * Test that methods with some parameters annotated with {@literal @}{@link All} behave correctly.
 */
@RunWith(JukitoRunner.class)
public class AllNamedAnnotationTest {

    public static final String FIRST = "first";
    public static final String SECOND = "second";

    static class Module extends JukitoModule {
        @SuppressWarnings("unchecked")
        @Override
        protected void configureTest() {
            bindManyNamedInstances(String.class, FIRST, "A", "B");
            bindManyNamedInstances(String.class, SECOND, "C", "D");
            bindManyNamedInstances(TestDataInstance.class, FIRST, new TestDataInstance("A"),
                    new TestDataInstance("B"));
            bindManyNamedInstances(TestDataInstance.class, SECOND, new TestDataInstance("C"),
                    new TestDataInstance("D"));
            bindManyNamed(TestData.class, FIRST, TestDataA.class, TestDataB.class);
            bindManyNamed(TestData.class, SECOND, TestDataC.class, TestDataD.class);

            bindManyNamedInstances(Integer.class, null, 1, 2, 3, 5);
        }
    }

    interface TestData {
        String getData();
    }

    static class TestDataA implements TestData {
        public String getData() {
            return "A";
        }
    }

    static class TestDataB implements TestData {
        public String getData() {
            return "B";
        }
    }

    static class TestDataC implements TestData {
        public String getData() {
            return "C";
        }
    }

    static class TestDataD implements TestData {
        public String getData() {
            return "D";
        }
    }

    static class TestDataInstance {
        private final String data;

        TestDataInstance(String data) {
            this.data = data;
        }

        public String getData() {
            return data;
        }
    }

    /**
     * This class keeps track of what happens in all the tests run in this
     * class. It's used to make sure all expected tests are called.
     */
    private static class Bookkeeper {
        static List<String> namedStringsProcessed = new ArrayList<String>();
        static List<String> namedDataProcessed = new ArrayList<String>();
        static List<String> namedDataInstanceProcessed = new ArrayList<String>();

        static List<String> stringsProcessed = new ArrayList<String>();
        static List<String> dataProcessed = new ArrayList<String>();
        static List<String> dataInstanceProcessed = new ArrayList<String>();

        static List<Integer> integerProcessed = new ArrayList<Integer>();
    }

    @Test
    public void testAllWithNamedInstance(@All(FIRST) String string1, @All(SECOND) String string2) {
        Bookkeeper.namedStringsProcessed.add(string1 + string2);
    }

    @Test
    public void testAllWithNamedClass(@All(FIRST) TestData data1, @All(SECOND) TestData data2) {
        Bookkeeper.namedDataProcessed.add(data1.getData() + data2.getData());
    }

    @Test
    public void testAllWithNamedClassInstance(
            @All(FIRST) TestDataInstance data1, @All(SECOND) TestDataInstance data2) {
        Bookkeeper.namedDataInstanceProcessed.add(data1.getData() + data2.getData());
    }

    @Test
    public void testAllWithInstance(@All String string1, @All String string2) {
        Bookkeeper.stringsProcessed.add(string1 + string2);
    }

    @Test
    public void testAllWithClass(@All TestData data1, @All TestData data2) {
        Bookkeeper.dataProcessed.add(data1.getData() + data2.getData());
    }

    @Test
    public void testAllWithClassInstance(@All TestDataInstance data1, @All TestDataInstance data2) {
        Bookkeeper.dataInstanceProcessed.add(data1.getData() + data2.getData());
    }

    @Test
    public void testAllWithNullAsName(@All Integer i) {
        Bookkeeper.integerProcessed.add(i);
    }

    @AfterClass
    public static void checkBookkeeper() {
        assertTrue(Bookkeeper.namedStringsProcessed.contains("AC"));
        assertTrue(Bookkeeper.namedStringsProcessed.contains("AD"));
        assertTrue(Bookkeeper.namedStringsProcessed.contains("BC"));
        assertTrue(Bookkeeper.namedStringsProcessed.contains("BD"));
        assertEquals(4, Bookkeeper.namedStringsProcessed.size());

        assertTrue(Bookkeeper.namedDataProcessed.contains("AC"));
        assertTrue(Bookkeeper.namedDataProcessed.contains("AD"));
        assertTrue(Bookkeeper.namedDataProcessed.contains("BC"));
        assertTrue(Bookkeeper.namedDataProcessed.contains("BD"));
        assertEquals(4, Bookkeeper.namedDataProcessed.size());

        assertTrue(Bookkeeper.namedDataInstanceProcessed.contains("AC"));
        assertTrue(Bookkeeper.namedDataInstanceProcessed.contains("AD"));
        assertTrue(Bookkeeper.namedDataInstanceProcessed.contains("BC"));
        assertTrue(Bookkeeper.namedDataInstanceProcessed.contains("BD"));
        assertEquals(4, Bookkeeper.namedDataInstanceProcessed.size());

        assertTrue(Bookkeeper.stringsProcessed.contains("AA"));
        assertTrue(Bookkeeper.stringsProcessed.contains("AB"));
        assertTrue(Bookkeeper.stringsProcessed.contains("AC"));
        assertTrue(Bookkeeper.stringsProcessed.contains("AD"));
        assertTrue(Bookkeeper.stringsProcessed.contains("BA"));
        assertTrue(Bookkeeper.stringsProcessed.contains("BB"));
        assertTrue(Bookkeeper.stringsProcessed.contains("BC"));
        assertTrue(Bookkeeper.stringsProcessed.contains("BD"));
        assertTrue(Bookkeeper.stringsProcessed.contains("CA"));
        assertTrue(Bookkeeper.stringsProcessed.contains("CB"));
        assertTrue(Bookkeeper.stringsProcessed.contains("CC"));
        assertTrue(Bookkeeper.stringsProcessed.contains("CD"));
        assertTrue(Bookkeeper.stringsProcessed.contains("DA"));
        assertTrue(Bookkeeper.stringsProcessed.contains("DB"));
        assertTrue(Bookkeeper.stringsProcessed.contains("DC"));
        assertTrue(Bookkeeper.stringsProcessed.contains("DD"));
        assertEquals(16, Bookkeeper.stringsProcessed.size());

        assertTrue(Bookkeeper.dataProcessed.contains("AA"));
        assertTrue(Bookkeeper.dataProcessed.contains("AB"));
        assertTrue(Bookkeeper.dataProcessed.contains("AC"));
        assertTrue(Bookkeeper.dataProcessed.contains("AD"));
        assertTrue(Bookkeeper.dataProcessed.contains("BA"));
        assertTrue(Bookkeeper.dataProcessed.contains("BB"));
        assertTrue(Bookkeeper.dataProcessed.contains("BC"));
        assertTrue(Bookkeeper.dataProcessed.contains("BD"));
        assertTrue(Bookkeeper.dataProcessed.contains("CA"));
        assertTrue(Bookkeeper.dataProcessed.contains("CB"));
        assertTrue(Bookkeeper.dataProcessed.contains("CC"));
        assertTrue(Bookkeeper.dataProcessed.contains("CD"));
        assertTrue(Bookkeeper.dataProcessed.contains("DA"));
        assertTrue(Bookkeeper.dataProcessed.contains("DB"));
        assertTrue(Bookkeeper.dataProcessed.contains("DC"));
        assertTrue(Bookkeeper.dataProcessed.contains("DD"));
        assertEquals(16, Bookkeeper.dataProcessed.size());

        assertTrue(Bookkeeper.dataInstanceProcessed.contains("AA"));
        assertTrue(Bookkeeper.dataInstanceProcessed.contains("AB"));
        assertTrue(Bookkeeper.dataInstanceProcessed.contains("AC"));
        assertTrue(Bookkeeper.dataInstanceProcessed.contains("AD"));
        assertTrue(Bookkeeper.dataInstanceProcessed.contains("BA"));
        assertTrue(Bookkeeper.dataInstanceProcessed.contains("BB"));
        assertTrue(Bookkeeper.dataInstanceProcessed.contains("BC"));
        assertTrue(Bookkeeper.dataInstanceProcessed.contains("BD"));
        assertTrue(Bookkeeper.dataInstanceProcessed.contains("CA"));
        assertTrue(Bookkeeper.dataInstanceProcessed.contains("CB"));
        assertTrue(Bookkeeper.dataInstanceProcessed.contains("CC"));
        assertTrue(Bookkeeper.dataInstanceProcessed.contains("CD"));
        assertTrue(Bookkeeper.dataInstanceProcessed.contains("DA"));
        assertTrue(Bookkeeper.dataInstanceProcessed.contains("DB"));
        assertTrue(Bookkeeper.dataInstanceProcessed.contains("DC"));
        assertTrue(Bookkeeper.dataInstanceProcessed.contains("DD"));
        assertEquals(16, Bookkeeper.dataInstanceProcessed.size());

        assertTrue(Bookkeeper.integerProcessed.contains(1));
        assertTrue(Bookkeeper.integerProcessed.contains(2));
        assertTrue(Bookkeeper.integerProcessed.contains(3));
        assertTrue(Bookkeeper.integerProcessed.contains(5));
        assertEquals(4, Bookkeeper.integerProcessed.size());
    }
}


================================================
FILE: jukito/src/test/java/org/jukito/AssistedInjectTest.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import com.google.inject.name.Named;
import com.google.inject.name.Names;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;

/**
 * Tests that new Guice 3.0 assisted injection works in Jukito.
 */
@RunWith(JukitoRunner.class)
public class AssistedInjectTest {

    /**
     * Guice test module.
     */
    static class Module extends JukitoModule {
        @Override
        protected void configureTest() {
            bindConstant().annotatedWith(Names.named("G")).to(6.673E-11);
            install(new FactoryModuleBuilder().implement(Payment.class, RealPayment.class)
                    .build(PaymentFactory.class));
            install(new FactoryModuleBuilder().implement(Star.class, StarImpl.class)
                    .build(StarFactory.class));
        }
    }

    interface PaymentFactory {
        Payment create(Date startDate, int amount);
    }

    interface Payment {
        String format();
    }

    static class RealPayment implements Payment {
        private final Date date;
        private final int amount;
        private final LocaleInfo localeInfo;

        @Inject
        RealPayment(@Assisted Date date, @Assisted int amount, LocaleInfo localeInfo) {
            this.date = date;
            this.amount = amount;
            this.localeInfo = localeInfo;
        }

        @Override
        public String format() {
            String result = "Paid " + Integer.toString(amount);
            if (localeInfo.isMoneySignBefore()) {
                result = localeInfo.getMoneySign() + result;
            } else {
                result += localeInfo.getMoneySign();
            }
            SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy", Locale.US);
            formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
            result += " on " + formatter.format(date);

            return result;
        }
    }

    interface LocaleInfo {
        String getMoneySign();

        boolean isMoneySignBefore();
    }

    interface StarFactory {
        Star create(String name, double mass);
    }

    interface Star {
        double getGravitationalConstant();

        double getMass();

        String getName();
    }

    static class StarImpl implements Star {
        private final double gravitationalConstant;
        private final double mass;
        private final String name;

        @Inject
        StarImpl(@Named("G") Double gravitationalConstant, @Assisted double mass,
                @Assisted String name) {
            this.gravitationalConstant = gravitationalConstant;
            this.mass = mass;
            this.name = name;
        }

        @Override
        public double getGravitationalConstant() {
            return gravitationalConstant;
        }

        @Override
        public double getMass() {
            return mass;
        }

        @Override
        public String getName() {
            return name;
        }
    }

    @Inject
    StarFactory starFactory;

    @Before
    public void setup(LocaleInfo localeInfo) {
        when(localeInfo.getMoneySign()).thenReturn("$");
        when(localeInfo.isMoneySignBefore()).thenReturn(false);
    }

    @Test
    public void testFactory(PaymentFactory factory) {
        // GIVEN
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"), Locale.US);
        calendar.set(2011, 4, 24); // Month is 0-based

        // WHEN
        Payment payment = factory.create(calendar.getTime(), 50);

        // THEN
        assertEquals("Paid 50$ on 05/24/2011", payment.format());
    }

    @Test
    public void testFactoryWithInjectedConstant() {
        // WHEN
        Star star = starFactory.create("Sun", 1.99E30);

        // THEN
        assertEquals("Sun", star.getName());
        assertEquals(1.99E30, star.getMass(), 0.000001);
        assertEquals(6.673E-11, star.getGravitationalConstant(), 0.000001);
    }
}


================================================
FILE: jukito/src/test/java/org/jukito/AutoBindMocksDisabledTest.java
================================================
/*
 * Copyright 2017 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;

import com.google.inject.PrivateModule;

import jakarta.inject.Inject;

/**
 * Tests behavior of autoBindMocks property on UseModules annotation.
 * NOTE: If autoBindMocks is true, this test will fail because SomeInterface will be auto bound
 * to a mock and the binding will conflict with private module's binding
 */
@RunWith(JukitoRunner.class)
@UseModules(value = AutoBindMocksDisabledTest.MyModule.class, autoBindMocks = false)
public class AutoBindMocksDisabledTest {

    /**
     * Guice PrivateModule for testing.
     */
    public static final class MyModule extends PrivateModule {

        @Override
        protected void configure() {
            bind(ExposedClass.class);
            bind(SomeInterface.class).to(NotAMock.class);
            expose(ExposedClass.class);
        }
    }

    /**
     * Test Interface that will be auto mocked if autoBindMocks is set to true.
     */
    public interface SomeInterface {
        void doSomething();
    }

    /**
     * When autoBindMocks is false, an instance of this type will be bound
     * to SomeInterface from the PrivateModule.
     */
    public static final class NotAMock implements SomeInterface {

        @Override
        public void doSomething() {
        }
    }

    /**
     * Class which injects either the automock or the concrete instance
     * depending on the autoBindMocks property.
     */
    public static final class ExposedClass {

        private SomeInterface instance;

        @Inject
        ExposedClass(final SomeInterface instance) {
            this.instance = instance;
        }

        SomeInterface getInstance() {
            return instance;
        }
    }

    @Test
    public void testSomething(final ExposedClass clazz) throws Exception {
        Assert.assertFalse(Mockito.mockingDetails(clazz).isMock());
        Assert.assertFalse(Mockito.mockingDetails(clazz.getInstance()).isMock());
    }
}


================================================
FILE: jukito/src/test/java/org/jukito/BindAnnotatedConcreteClassesTest.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import org.junit.Test;
import org.junit.runner.RunWith;

import com.google.inject.name.Named;

import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;

/**
 * Test that annotated concrete classes can be correctly bound.
 * See http://code.google.com/p/jukito/issues/detail?id=12
 */
@RunWith(JukitoRunner.class)
public class BindAnnotatedConcreteClassesTest {

    /**
     * Guice test module.
     */
    static class Module extends JukitoModule {
        @Override
        protected void configureTest() {
            bindNamed(ConcreteClass.class, "a").to(ConcreteClass.class).in(TestSingleton.class);
            bindNamed(ConcreteClass.class, "b").to(ConcreteClass.class).in(TestSingleton.class);
            bindNamed(ConcreteClass.class, "c").to(SubConcreteClass.class);
            bindNamed(ConcreteClass.class, "d").to(SubConcreteClass.class);
            bind(SubConcreteClass.class).in(TestSingleton.class);
            bind(SubSubConcreteClass.class);
        }
    }

    static class ConcreteClass {
    }

    static class SubConcreteClass extends ConcreteClass {
    }

    static class SubSubConcreteClass extends ConcreteClass {
    }

    @Test
    public void testConcreteClassBoundToDifferentSingletons(@Named("a") ConcreteClass a,
            @Named("b") ConcreteClass b) {
        // THEN
        assertNotSame(a, b);
    }

    @Test
    public void testConcreteClassBoundToSameSingleton(@Named("c") ConcreteClass c,
            @Named("d") ConcreteClass d) {
        // THEN
        assertSame(c, d);
    }

    @Test
    public void testConcreteClassNoBoundAsSingleton(SubSubConcreteClass instance1,
            SubSubConcreteClass instance2) {
        // THEN
        assertNotSame(instance1, instance2);
    }
}


================================================
FILE: jukito/src/test/java/org/jukito/BindSpyInstanceTest.java
================================================
/**
 * Copyright 2014 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

/**
 * Bind spy instance test.
 */
@RunWith(JukitoRunner.class)
public class BindSpyInstanceTest {

    /**
     * Guice test module.
     */
    static class Module extends JukitoModule {
        @Override
        protected void configureTest() {
            bindSpy(SimpleClass.class, new SimpleClass("foo")).in(TestScope.SINGLETON);
        }
    }

    static class SimpleClass {
        private String arg0;

        @SuppressWarnings("unused")
        SimpleClass() {
            this("default");
        }

        SimpleClass(String arg0) {
            this.arg0 = arg0;
        }

        String getVal() {
            return arg0;
        }
    }

    @Test
    public void testOneInvocation(SimpleClass simple) {
        String value = simple.getVal();

        assertEquals("foo", value);

        verify(simple).getVal();
    }

    @Test
    public void testNeverInvoked(SimpleClass simple) {
        verify(simple, never()).getVal();
    }
}


================================================
FILE: jukito/src/test/java/org/jukito/BindSpyTest.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import org.junit.Test;
import org.junit.runner.RunWith;

import com.google.inject.Inject;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

/**
 * Test that binding spy works correctly.
 */
@RunWith(JukitoRunner.class)
public class BindSpyTest {

    /**
     * Guice test module.
     */
    static class Module extends JukitoModule {
        @Override
        protected void configureTest() {
            bindSpy(SimpleClass.class).in(TestScope.SINGLETON);
        }
    }

    interface CompositionMockA {
        String test();
    }

    interface CompositionMockB {
        String test();
    }

    static class SimpleClass {
        @Inject
        CompositionMockB mockB;

        private CompositionMockA mockA;

        @Inject
        SimpleClass(CompositionMockA mockA) {
            this.mockA = mockA;
        }

        String callTestMethodOnMock() {
            mockA.test();
            mockB.test();
            return "Default string";
        }
    }

    @Inject
    CompositionMockA mockA;
    @Inject
    CompositionMockA mockB;

    @Test
    public void testStubbingSpiedInstance(SimpleClass simpleClass) {
        // GIVEN
        doReturn("Mocked string").when(simpleClass).callTestMethodOnMock();

        // WHEN
        String result = simpleClass.callTestMethodOnMock();

        // THEN
        assertEquals("Mocked string", result);
        verify(mockA, never()).test();
        verify(mockB, never()).test();
    }

    @Test
    public void testNotStubbingSpiedInstance(SimpleClass simpleClass) {
        // WHEN
        String result = simpleClass.callTestMethodOnMock();

        // THEN
        verify(mockA).test();
        verify(mockB).test();
        assertEquals("Default string", result);
    }
}


================================================
FILE: jukito/src/test/java/org/jukito/BindingToProviderTest.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import org.junit.Test;
import org.junit.runner.RunWith;

import com.google.inject.Provides;

import jakarta.inject.Provider;

import static org.junit.Assert.assertEquals;

/**
 * A test to make sure injecting a Provider in a @Provides method.
 * See https://github.com/ArcBees/Jukito/issues/34
 */
@RunWith(JukitoRunner.class)
public class BindingToProviderTest {

    /**
     * Guice test module.
     */
    public static class MyModule extends JukitoModule {
        @Provides
        public final MyClass getObject(Provider<String> provider) {
            return new MyClass("abc" + provider.get());
        }

        @Override
        protected void configureTest() {
            bind(String.class).toInstance("def");
        }
    }

    static class MyClass {
        private final String string;

        MyClass(String string) {
            this.string = string;
        }

        String getString() {
            return string;
        }
    }

    @Test
    public void foo(MyClass obj) {
        assertEquals("abcdef", obj.getString());
    }
}


================================================
FILE: jukito/src/test/java/org/jukito/EDRunner.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.util.ArrayList;
import java.util.List;

import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.ParentRunner;

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;

/**
 * Runner allows to run the all test methods in environment build upon different implementations
 * via dedicated Injectors per test run.
 */
public class EDRunner extends ParentRunner {
    private List<Runner> runnersList;

    public EDRunner(Class<?> testClass) throws Exception {
        super(testClass);
        runnersList = createJukitoRunners(testClass);
    }

    public List<Runner> createJukitoRunners(Class<?> testClass) throws Exception {
        List<Runner> result = new ArrayList<Runner>();

        for (Injector injector : calculateInjectors(testClass)) {
            JukitoRunner jukitoRunner = new JukitoRunner(testClass, injector);
            result.add(jukitoRunner);
        }

        return result;
    }

    protected List<Injector> calculateInjectors(Class<?> testClass)
            throws IllegalAccessException, InstantiationException {
        List<Injector> result = new ArrayList<Injector>();

        EnvironmentDependentModules environmentDependentModules
                = testClass.getAnnotation(EnvironmentDependentModules.class);

        if (environmentDependentModules == null) {
            throw new RuntimeException(EnvironmentDependentModules.class + " not found on test class");
        }

        for (Class edModuleClass : environmentDependentModules.value()) {
            Injector i = buildInjector(edModuleClass, testClass);
            result.add(i);
        }

        return result;
    }

    @Override
    protected List getChildren() {
        return runnersList;
    }

    @Override
    protected Description describeChild(Object child) {
        return ((JukitoRunner) child).getDescription();
    }

    @Override
    protected void runChild(Object child, RunNotifier notifier) {
        ((JukitoRunner) child).run(notifier);
    }

    private Injector buildInjector(Class<? extends Module> edModuleClazz, final Class<?> testClass)
            throws InstantiationException, IllegalAccessException {

        final Module environmentDependentModule = edModuleClazz.newInstance();

        final AbstractModule testModule = new AbstractModule() {
            @Override
            protected void configure() {
                for (Module declaredModule : getDeclaredModulesForTest(testClass)) {
                    install(declaredModule);
                }
                install(environmentDependentModule);
            }
        };

        JukitoModule finalModule = new JukitoModule() {
            @Override
            protected void configureTest() {
                install(testModule);
            }
        };

        BindingsCollector collector = new BindingsCollector(finalModule);
        collector.collectBindings();
        finalModule.setBindingsObserved(collector.getBindingsObserved());

        return Guice.createInjector(finalModule);
    }

    // TODO refactor to common user module discovery method (JukitoRunner uses similar code now)
    private Module[] getDeclaredModulesForTest(Class<?> testClass) {
        UseModules useModules = testClass.getAnnotation(UseModules.class);
        Class<? extends Module>[] moduleClasses = useModules.value();
        final Module[] modules = new Module[moduleClasses.length];
        for (int i = 0; i < modules.length; i++) {
            try {
                modules[i] = moduleClasses[i].newInstance();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return modules;
    }
}


================================================
FILE: jukito/src/test/java/org/jukito/EnvironmentDependentComponent.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

/**
 * Sample interface which have implementations bound in different guice context (Injectors).
 */
public interface EnvironmentDependentComponent {
    void hello();
}


================================================
FILE: jukito/src/test/java/org/jukito/ExternalSingleton.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import com.google.inject.Singleton;

/**
 * A class annotated with @Singleton not defined within test class.
 */
@Singleton
public class ExternalSingleton {
}


================================================
FILE: jukito/src/test/java/org/jukito/ForceMockTest.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

/**
 * Test that the {@link org.jukito.JukitoModule#forceMock} method works as expected.
 */
@RunWith(JukitoRunner.class)
public class ForceMockTest {

    /**
     * Guice test module.
     */
    static class Module extends JukitoModule {
        @Override
        protected void configureTest() {
            forceMock(Base1.class);
            forceMock(Child21.class);
            forceMock(Child311.class);
        }
    }

    interface Base1 {
        int t1();
    }

    static class Child11 implements Base1 {
        public int t1() {
            return 11;
        }
    }

    static class Child111 extends Child11 {
        public int t1() {
            return 111;
        }
    }

    static class Child12 implements Base1 {
        public int t1() {
            return 12;
        }
    }

    interface Base2 {
        int t2();
    }

    static class Child21 implements Base2 {
        public int t2() {
            return 21;
        }
    }

    static class Child211 extends Child21 {
        public int t2() {
            return 211;
        }
    }

    static class Child22 implements Base2 {
        public int t2() {
            return 22;
        }
    }

    interface Base3 {
        int t3();
    }

    static class Child31 implements Base3 {
        public int t3() {
            return 31;
        }
    }

    static class Child311 extends Child31 {
        public int t3() {
            return 311;
        }
    }

    @Test
    public void injectForceMock(
            Base1 base1,
            Child11 child11,
            Child111 child111,
            Child12 child12,
            Base2 base2,
            Child21 child21,
            Child211 child211,
            Child22 child22,
            Base3 base3,
            Child31 child31,
            Child311 child311) {
        verify(base1, never()).t1();
        verify(child11, never()).t1();
        verify(child111, never()).t1();
        verify(child12, never()).t1();

        verify(base2, never()).t2();
        verify(child21, never()).t2();
        verify(child211, never()).t2();
        assertEquals(22, child22.t2());

        verify(base3, never()).t3();
        assertEquals(31, child31.t3());
        verify(child311, never()).t3();
    }
}


================================================
FILE: jukito/src/test/java/org/jukito/GeneralTest.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.util.logging.Logger;

import org.junit.Test;
import org.junit.runner.RunWith;

import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.MembersInjector;
import com.google.inject.Stage;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;
import com.google.inject.name.Names;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

/**
 * Test various general behaviors.
 */
@RunWith(JukitoRunner.class)
public class GeneralTest {
    /**
     * Guice test module.
     */
    static class Module extends JukitoModule {
        @Override
        protected void configureTest() {
            bindConstant().annotatedWith(OneHundred.class).to(100);
            bindConstant().annotatedWith(Names.named("200")).to(200);
            bindConstant().annotatedWith(Names.named("HelloWorld")).to("Hello World!");
            bindConstant().annotatedWith(Names.named("500L")).to(500L);
            bindConstant().annotatedWith(Names.named("true")).to(true);
            bindConstant().annotatedWith(Names.named("3.1415")).to(3.1415);
            bindConstant().annotatedWith(Names.named("2.718f")).to(2.718f);
            bindConstant().annotatedWith(Names.named("short8")).to((short) 8);
            bindConstant().annotatedWith(Names.named("'a'")).to('a');
            bindConstant().annotatedWith(Names.named("IntegerClass")).to(Integer.class);
            bindConstant().annotatedWith(Names.named("VALUE1")).to(MyEnum.VALUE1);
            bindConstant().annotatedWith(Names.named("VALUE2")).to(MyEnum.VALUE2);
            bind(MyInteger.class).annotatedWith(OneHundred.class).toInstance(new MyIntegerImpl(100));
            bind(MyInteger.class).annotatedWith(Names.named("200")).toInstance(new MyIntegerImpl(200));
            bind(Key.get(TestClass.class, Value3.class)).toInstance(new TestClass(MyEnum.VALUE3));
            bind(Key.get(TestClass.class, Names.named("VALUE2"))).to(TestClass.class).in(
                    TestSingleton.class);
            bind(new TypeLiteral<ParameterizedTestClass<Integer>>() {
            }).in(TestScope.SINGLETON);
            bind(new TypeLiteral<ParameterizedTestClass<Double>>() {
            }).to(
                    ParameterizedTestClassDouble.class).in(TestScope.SINGLETON);
            bindNamedMock(ClassWithUninstanciableDependency3.class, "UninstanciableDependency3a");
            bind(ClassWithUninstanciableDependency3.class).annotatedWith(
                    Names.named("UninstanciableDependency3b")).toProvider(MyMockProvider3b.class);
            bind(ClassWithUninstanciableDependency3.class).annotatedWith(
                    Names.named("UninstanciableDependency3c")).toProvider(Key.get(MyMockProvider3c.class));
            try {
                bind(ParameterizedTestClassString.class).toConstructor(
                        ParameterizedTestClassString.class.getConstructor(String.class));
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
            // TODO: Try to bind a mock logger once Issue 9 is solved.
            // bindMock(Logger.class);
        }
    }

    interface MyInteger {
        int getValue();
    }

    static class MyIntegerImpl implements MyInteger {
        private final int value;

        MyIntegerImpl(int value) {
            this.value = value;
        }

        @Override
        public int getValue() {
            return value;
        }
    }

    enum MyEnum {
        VALUE1,
        VALUE2,
        VALUE3
    }

    static class TestClass {
        private final MyEnum value;

        @Inject
        TestClass(@Named("VALUE2") MyEnum value) {
            this.value = value;
        }
    }

    static class ParameterizedTestClass<T> {
        final T value;

        @Inject
        ParameterizedTestClass(@Named("200") T value) {
            this.value = value;
        }
    }

    static class ParameterizedTestClassDouble extends ParameterizedTestClass<Double> {
        @Inject
        ParameterizedTestClassDouble() {
            super(10.0);
        }
    }

    public static class ParameterizedTestClassString extends ParameterizedTestClass<String> {
        ParameterizedTestClassString() {
            super("default constructor");
        }

        public ParameterizedTestClassString(@Named("HelloWorld") String value) {
            super(value);
        }
    }

    static class TestClassWithMethodInjection {
        private int value;

        @Inject
        TestClassWithMethodInjection(@OneHundred Integer value) {
            this.value = value;
        }

        @Inject
        public void setValue(@Named("200") Integer value) {
            this.value = value;
        }
    }

    interface NonBoundInterface {
        int getValue();
    }

    static class TestClassWithOptionalInjection {
        private int value;

        @Inject
        TestClassWithOptionalInjection(@OneHundred Integer value) {
            this.value = value;
        }

        @Inject(optional = true)
        public void setValue(NonBoundInterface obj) {
            value = obj.getValue(); // Should never be called, NonBoundInterface should not be mocked
        }
    }

    // This class will cause an error if bound
    static class UninstanciableClass {
        private UninstanciableClass() {
        }

        public int getValue() {
            return 360;
        }
    }

    @TestMockSingleton
    static class ClassWithUninstanciableDependency1 {
        private final UninstanciableClass dependency;

        @Inject
        ClassWithUninstanciableDependency1(UninstanciableClass dependency) {
            this.dependency = dependency;
        }

        public int getValue() {
            return 42;
        }

        public UninstanciableClass getDependency() {
            return dependency;
        }
    }

    abstract static class ClassWithUninstanciableDependency2 {
        @Inject
        ClassWithUninstanciableDependency2(UninstanciableClass dependency) {
        }

        public int getValue() {
            return 42;
        }
    }

    static class ClassWithUninstanciableDependency3 {
        @Inject
        ClassWithUninstanciableDependency3(UninstanciableClass dependency) {
        }

        public int getValue() {
            return 42;
        }
    }

    static class MyMockProvider3b extends MockProvider<ClassWithUninstanciableDependency3> {
        @Inject
        MyMockProvider3b() {
            super(ClassWithUninstanciableDependency3.class);
        }
    }

    static class MyMockProvider3c extends MockProvider<ClassWithUninstanciableDependency3> {
        @Inject
        MyMockProvider3c() {
            super(ClassWithUninstanciableDependency3.class);
        }
    }

    static class TestGenericClassInjectedWithTypeLiteral<U> {
        private final Class<? super U> injectedType;

        @Inject
        TestGenericClassInjectedWithTypeLiteral(TypeLiteral<U> typeLiteral) {
            injectedType = typeLiteral.getRawType();
        }

        public Class<? super U> getInjectedType() {
            return injectedType;
        }
    }

    @Test
    public void testConstantInjection(
            @OneHundred Integer oneHundred,
            @Named("200") Integer twoHundred,
            @Named("HelloWorld") String helloWorld,
            @Named("500L") long fiveHundred,
            @Named("3.1415") double pi,
            @Named("2.718f") float e,
            @Named("short8") short eight,
            @Named("'a'") char a,
            @SuppressWarnings("rawtypes")
            @Named("IntegerClass") Class integerClass,
            @Named("VALUE1") MyEnum value1) {
        assertEquals(100, (int) oneHundred);
        assertEquals(200, (int) twoHundred);
        assertEquals("Hello World!", helloWorld);
        assertEquals(500L, fiveHundred);
        assertEquals(3.1415, pi, 0.0000001);
        assertEquals(2.718f, e, 0.00001);
        assertEquals(8, eight);
        assertEquals('a', a);
        assertEquals(Integer.class, integerClass);
        assertEquals(MyEnum.VALUE1, value1);
    }

    @Test
    public void testInjectBoundWithKeys(
            @Value3 TestClass testClassValue3,
            @Named("VALUE2") TestClass testClassValue2,
            @OneHundred MyInteger testMyInteger100,
            @Named("200") MyInteger testMyInteger200) {
        assertEquals(MyEnum.VALUE3, testClassValue3.value);
        assertEquals(MyEnum.VALUE2, testClassValue2.value);
        assertEquals(100, testMyInteger100.getValue());
        assertEquals(200, testMyInteger200.getValue());
    }

    @Test
    public void testParameterizedInjection1(
            ParameterizedTestClass<Integer> testClass) {
        assertEquals(200, (int) testClass.value);
    }

    @Test
    public void testParameterizedInjection2(
            ParameterizedTestClass<Double> testClass) {
        assertEquals(10.0, (double) testClass.value, 0.0000001);
    }

    @Test
    public void testMethodInjection(
            TestClassWithMethodInjection testClass) {
        assertEquals(200, testClass.value);
    }

    @Test
    public void testOptionalInjection(
            TestClassWithOptionalInjection testClass) {
        assertEquals(100, testClass.value);
    }

    @Test
    public void testInjectingMockShouldNotInstantiateDependencies1(
            ClassWithUninstanciableDependency1 testClass) {
        assertEquals(42, testClass.getValue());
        verify(testClass.getDependency(), never()).getValue();
    }

    @Test
    public void testInjectingMockShouldNotInstantiateDependencies2(
            ClassWithUninstanciableDependency2 testClass) {
        verify(testClass, never()).getValue();
    }

    @Test
    public void testInjectingMockShouldNotInstantiateDependencies3a(
            @Named("UninstanciableDependency3a") ClassWithUninstanciableDependency3 testClass) {
        verify(testClass, never()).getValue();
    }

    @Test
    public void testInjectingMockShouldNotInstantiateDependencies3b(
            @Named("UninstanciableDependency3b") ClassWithUninstanciableDependency3 testClass) {
        verify(testClass, never()).getValue();
    }

    @Test
    public void testInjectingMockShouldNotInstantiateDependencies3c(
            @Named("UninstanciableDependency3c") ClassWithUninstanciableDependency3 testClass) {
        verify(testClass, never()).getValue();
    }

    @Test
    public void testInjectingClassInjectedWithTypeLiteralShouldWork(
            TestGenericClassInjectedWithTypeLiteral<String> testClass) {
        assertEquals(String.class, testClass.getInjectedType());
    }

    @Test
    public void testInjectingTypeLiteralShouldWork(
            TypeLiteral<Integer> typeLiteral) {
        assertEquals(Integer.class, typeLiteral.getRawType());
    }

    @Test
    public void testInjectingInjectorShouldWork(
            Injector injector) {
    }

    @Test
    public void testInjectingLoggerShouldWork(
            Logger logger) {
    }

    @Test
    public void testInjectingStageShouldWork(
            Stage stage) {
    }

    @Test
    public void testInjectingMembersInjectorShouldWork(
            MembersInjector<TestClass> memberInjector) {
    }

    @Test
    public void toConstructorInjectionShouldWork(ParameterizedTestClassString object) {
        assertEquals("Hello World!", object.value);
    }
}


================================================
FILE: jukito/src/test/java/org/jukito/InnerClassTest.java
================================================
/**
 * Copyright 2014 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import org.junit.Test;
import org.junit.runner.RunWith;

import com.google.inject.ConfigurationException;
import com.google.inject.Inject;

import static org.junit.Assert.assertEquals;

/**
 * Test to ensure that injecting inner classes throw a ConfigurationException, instead
 * of simply injecting a mock. Additionally, test that injecting static inner classes
 * still work properly.
 */
@RunWith(JukitoRunner.class)
public class InnerClassTest {
    /**
     * Test module, just bind anything to make sure regular injections still work properly.
     */
    public static class Module extends JukitoModule {
        @Override
        protected void configureTest() {
            bind(String.class).toInstance("hello world!");
        }
    }

    /**
     * Dummy inner class with a single inject.
     */
    class InnerClass {
        @Inject
        String test;

        public String toString() {
            return test;
        }
    }

    /**
     * Dummy static inner class with a single inject.
     */
    static class StaticInnerClass {
        @Inject
        String test;

        public String toString() {
            return test;
        }
    }

    /**
     * Verify that when you try to inject an inner class, a ConfigurationException is thrown.
     *
     * @param klass
     */
    @Test(expected = ConfigurationException.class)
    public void testInnerClass(InnerClass klass) {
        assertEquals("hello world!", klass.toString());
    }

    /**
     * Verify that when you try to inject a static inner class, everything works properly.
     *
     * @param klass
     */
    @Test
    public void testStaticInnerClass(StaticInnerClass klass) {
        assertEquals("hello world!", klass.toString());
    }
}


================================================
FILE: jukito/src/test/java/org/jukito/InstallTest.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.name.Named;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;

/**
 * Test exercising Guice's install() mechanism.
 */
@RunWith(JukitoRunner.class)
public class InstallTest {

    /**
     * Guice test module, containing two submodules.
     */
    static class Module extends JukitoModule {

        public class FooModule extends AbstractModule {

            @Override
            protected void configure() {
                bind(Foo.class).to(FooImpl.class);
            }
        }

        public class BarModule extends AbstractModule {

            @Override
            protected void configure() {
                bind(Bar.class).to(BarImpl.class);
            }
        }

        @Override
        protected void configureTest() {
            install(new FooModule());
            install(new BarModule());
            bindNamedMock(Foo.class, "ten").in(TestSingleton.class);
        }
    }

    interface Foo {
        int calc();
    }

    static class FooImpl implements Foo {

        private final Provider<Bar> barProvider;
        private final Foo ten;

        @Inject
        FooImpl(Provider<Bar> barProvider, @Named("10") Foo ten) {
            this.barProvider = barProvider;
            this.ten = ten;
        }

        @Override
        public int calc() {
            return this.barProvider.get().calc() + ten.calc();
        }
    }

    interface Bar {
        int calc();
    }

    static class BarImpl implements Bar {
        @Override
        public int calc() {
            return 5;
        }
    }

    @Inject
    Foo foo;

    @Before
    public void setup(@Named("10") Foo ten) {
        when(ten.calc()).thenReturn(10);
    }

    @Test
    public void installingModuleWorks(Bar bar) {
        assertEquals(15, foo.calc());
        assertEquals(5, bar.calc());
    }
}


================================================
FILE: jukito/src/test/java/org/jukito/ModuleWithProvidesMethods.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.jukito;

import com.google.inject.AbstractModule;
import com.google.inject.Provides;

import static org.mockito.Mockito.mock;

/**
 * Simple module with factory method.
 */
public class ModuleWithProvidesMethods extends AbstractModule {

    @Provides
    @TestSingleton
    SomeTestClass create() {
        SomeTestClass mock = mock(SomeTestClass.class);
        mock.someInitMethod();
        return mock;
    }

    @Override
    protected void configure() {
    }
}


================================================
FILE: jukito/src/test/java/org/jukito/NoModuleTest.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.assertSame;
import static org.mockito.Mockito.verify;

/**
 * Test to ensure injection works well without a module.
 */
@RunWith(JukitoRunner.class)
public class NoModuleTest {

    interface MyMockSingleton {
        int dummy();
    }

    @TestMockSingleton
    interface MyAnnotatedMockSingleton {
        int dummy();
    }

    static class MySingleton {
    }

    @TestSingleton
    static class MyAnnotatedSingleton {
    }

    @TestEagerSingleton
    static class MyAnnotatedEagerSingleton {
    }

    @Test
    public void testMockSingleton(MyMockSingleton a, MyMockSingleton b) {
        assertSame(a, b);
        a.dummy();
        verify(a).dummy();
        verify(b).dummy();
    }

    @Test
    public void testAnnotatedMockSingleton(MyAnnotatedMockSingleton a,
            MyAnnotatedMockSingleton b) {
        assertSame(a, b);
        a.dummy();
        verify(a).dummy();
        verify(b).dummy();
    }

    @Test
    public void testSingleton(MySingleton a, MySingleton b) {
        assertSame(a, b);
    }

    @Test
    public void testAnnotatedSingleton(MyAnnotatedSingleton a, MyAnnotatedSingleton b) {
        assertSame(a, b);
    }

    @Test
    public void testAnnotatedEagerSingleton(MyAnnotatedEagerSingleton a,
            MyAnnotatedEagerSingleton b) {
        assertSame(a, b);
    }
}


================================================
FILE: jukito/src/test/java/org/jukito/OldStyleAssistedInjectTest.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import org.junit.Test;
import org.junit.runner.RunWith;

import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.FactoryProvider;
import com.google.inject.name.Named;
import com.google.inject.name.Names;

import static org.junit.Assert.assertEquals;

/**
 * Test that make sure old-style Guice 2.0 assisted injection is supported.
 */
@SuppressWarnings("deprecation")
@RunWith(JukitoRunner.class)
public class OldStyleAssistedInjectTest {
    /**
     * Guice test module.
     */
    public static class Module extends JukitoModule {
        @Override
        protected void configureTest() {
            bindConstant().annotatedWith(Names.named("moneySymbol")).to("$");
            bindNamed(PaymentFactory.class, "factory1").toProvider(
                    FactoryProvider.newFactory(PaymentFactory.class, RealPayment1.class));
            bindNamed(PaymentFactory.class, "factory2").toProvider(
                    FactoryProvider.newFactory(PaymentFactory.class, RealPayment2.class));
            bind(PaymentAmountFactory.class).toProvider(
                    FactoryProvider.newFactory(PaymentAmountFactory.class, RealPaymentAmount.class));
            bind(Amount.class).toInstance(new Amount() {
                public String toString() {
                    return "An amount of 10.00 ";
                }
            });
        }
    }

    interface PaymentFactory {
        Payment create(int amount);
    }

    interface PaymentAmountFactory {
        Payment create(Amount amount);
    }

    interface Payment {
        String getPayment();
    }

    static class RealPayment1 implements Payment {
        private final String moneySymbol;
        private final int amount;

        @Inject
        RealPayment1(@Named("moneySymbol") String moneySymbol, @Assisted int amount) {
            this.moneySymbol = moneySymbol;
            this.amount = amount;
        }

        @Override
        public String getPayment() {
            return Integer.toString(amount) + ".00" + moneySymbol;
        }
    }

    static class RealPayment2 implements Payment {
        private final int amount;

        @Inject
        RealPayment2(@Assisted int amount) {
            this.amount = amount;
        }

        @Override
        public String getPayment() {
            return Integer.toString(amount) + " dollars";
        }
    }

    interface Amount {
        String toString();
    }

    // Interface Configuration should be mocked because it is a dependency
    // of RealPaymentAmout. The mocked version of {@ocde shouldAlwaysHideAmounts()}
    // will always return {@code false}.
    interface Configuration {
        boolean shouldAlwaysHideAmounts();
    }

    // Class InjectedClass should be bound automatically
    // because it is a dependency of RealPaymentAmount
    static class InjectedClass {
        @Inject
        @Named("moneySymbol")
        String moneySymbol;
    }

    static class RealPaymentAmount implements Payment {
        private final Configuration configuration;
        private final InjectedClass injectedClass;
        private final Amount amount;

        @Inject
        RealPaymentAmount(Configuration configuration,
                InjectedClass injectedClass,
                @Assisted Amount amount) {
            this.configuration = configuration;
            this.injectedClass = injectedClass;
            this.amount = amount;
        }

        @Override
        public String getPayment() {
            if (configuration.shouldAlwaysHideAmounts()) {
                return "xxxxxxx " + injectedClass.moneySymbol;
            }
            return amount.toString() + injectedClass.moneySymbol;
        }
    }

    @Inject
    @Named("factory1")
    PaymentFactory factory1;

    @Test
    public void shouldInjectFactoryInClass() {
        // WHEN
        Payment payment = factory1.create(20);

        // THEN
        assertEquals("20.00$", payment.getPayment());
    }

    @Test
    public void shouldInjectFactoryAsParameter(@Named("factory2") PaymentFactory factory2) {
        // WHEN
        Payment payment = factory2.create(30);

        // THEN
        assertEquals("30 dollars", payment.getPayment());
    }

    @Test
    public void shouldInjectFactoryWithInterfacesAsParameter(
            PaymentAmountFactory factoryString,
            Amount amount) {
        // WHEN
        Payment payment = factoryString.create(amount);

        // THEN
        assertEquals("An amount of 10.00 $", payment.getPayment());
    }
}


================================================
FILE: jukito/src/test/java/org/jukito/OneHundred.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import com.google.inject.BindingAnnotation;

/**
 * An annotation used in a test class.
 */
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface OneHundred {
}


================================================
FILE: jukito/src/test/java/org/jukito/ParentClassInnerClassModuleDiscoveryTest.java
================================================
/*
 * Copyright 2017 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import java.util.concurrent.atomic.AtomicInteger;

import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
 * Test which ensures that nested TestModules in parent classes are discovered by the JukitoRunner.
 */
@RunWith(JukitoRunner.class)
public class ParentClassInnerClassModuleDiscoveryTest extends SampleParentTestClassWithInnerTestModule {

    private static final AtomicInteger numberOfTestRuns = new AtomicInteger(0);

    @AfterClass
    public static void afterClass() throws Exception {
        Assert.assertEquals(2, numberOfTestRuns.get());
    }

    @Test
    public void testSomething(@All final String bindingsFromParent) throws Exception {
        numberOfTestRuns.incrementAndGet();
    }
}


================================================
FILE: jukito/src/test/java/org/jukito/ParentTestClassBase.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

import com.google.inject.Inject;
import com.google.inject.Provider;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

/**
 * This parent test class is used by {@link ParentTestClassTest}.
 */
@Ignore("Tests in this base class are not meant to be run independantly.")
public class ParentTestClassBase {

    /**
     * This should be automatically injected in the child class.
     */
    @TestSingleton
    static class SingletonDefinedInParent {
        private String value = "SingletonDefinedInParentValue";

        public String getValue() {
            return value;
        }
    }

    /**
     * This should be automatically injected in the child class.
     */
    @TestMockSingleton
    interface MockSingletonDefinedInParent {
        void mockSingletonMethod();
    }

    interface DummyInterface {
        String getDummyValue();
    }

    interface DummyInterfaceUsedOnlyInParent1 {
        String getDummyValue();
    }

    interface DummyInterfaceUsedOnlyInParent2 {
        String getDummyValue();
    }

    interface DummyInterfaceUsedOnlyInParent3 {
        String getDummyValue();
    }

    static class DummyClassUsedOnlyInParent1 {
    }

    static class DummyClassUsedOnlyInParent2 {
    }

    static class DummyClassUsedOnlyInParent3 {
    }

    @Inject
    protected Provider<DummyInterface> dummyProvider;
    @Inject
    protected MockSingletonDefinedInParent mockSingletonDefinedInParent;

    /**
     * This class keeps track of what happens in all the tests run in this
     * class and its child. It's used to make sure all expected tests are called.
     */
    protected static class Bookkeeper {
        static boolean parentTestShouldRunExecuted;
    }

    @Test
    public void parentTestShouldRun() {
        Bookkeeper.parentTestShouldRunExecuted = true;
    }

    @Test
    public void interfaceBoundInChildIsInjectedInParent() {
        assertEquals("DummyValue", dummyProvider.get().getDummyValue());
    }

    @Test
    public void interfaceBoundInChildIsInjectedInParentTestMethod(
            DummyInterface dummyInterface) {
        assertEquals("DummyValue", dummyInterface.getDummyValue());
    }

    @Test
    public void interfaceUsedInParentTestMethodShouldBeMockedAsTestSingleton(
            Provider<DummyInterfaceUsedOnlyInParent1> provider) {
        // Following should not crash
        verify(provider.get(), never()).getDummyValue();

        assertSame(provider.get(), provider.get());
    }

    @Test
    public void concreteClassUsedInParentTestMethodShouldBeBoundAsTestSingleton(
            Provider<DummyClassUsedOnlyInParent1> provider) {
        assertSame(provider.get(), provider.get());
    }

    @Before
    public void interfaceUsedInParentBeforeMethodShouldBeMockedAsTestSingleton(
            Provider<DummyInterfaceUsedOnlyInParent2> provider) {
        // Following should not crash
        verify(provider.get(), never()).getDummyValue();

        assertSame(provider.get(), provider.get());
    }

    @Before
    public void concreteClassUsedInParentBeforeMethodShouldBeBoundAsTestSingleton(
            Provider<DummyClassUsedOnlyInParent2> provider) {
        assertSame(provider.get(), provider.get());
    }

    @After
    public void interfaceUsedInParentAfterMethodShouldBeMockedAsTestSingleton(
            Provider<DummyInterfaceUsedOnlyInParent3> provider) {
        // Following should not crash
        verify(provider.get(), never()).getDummyValue();

        assertSame(provider.get(), provider.get());
    }

    @After
    public void concreteClassUsedInParentAfterMethodShouldBeBoundAsTestSingleton(
            Provider<DummyClassUsedOnlyInParent3> provider) {
        assertSame(provider.get(), provider.get());
    }
}


================================================
FILE: jukito/src/test/java/org/jukito/ParentTestClassTest.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import org.junit.AfterClass;
import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

/**
 * Test that inheritance of test classes works correctly.
 */
@RunWith(JukitoRunner.class)
public class ParentTestClassTest extends ParentTestClassBase {

    /**
     * Guice test module.
     */
    static class Module extends JukitoModule {
        @Override
        protected void configureTest() {
            bind(DummyInterface.class).to(MyDummyClass.class).in(TestScope.SINGLETON);
        }
    }

    /**
     * This class should be injected in parent tests.
     */
    static class MyDummyClass implements DummyInterface {
        @Override
        public String getDummyValue() {
            return "DummyValue";
        }
    }

    @Test
    public void mockSingletonDefinedInParentShouldBeBoundAsAMock() {
        verify(mockSingletonDefinedInParent, never()).mockSingletonMethod();
    }

    @Test
    public void singletonDefinedInParentShouldBeBound(
            SingletonDefinedInParent singletonDefinedInParent) {
        assertEquals("SingletonDefinedInParentValue", singletonDefinedInParent.getValue());
    }

    @AfterClass
    public static void checkBookkeeper() {
        assertTrue(Bookkeeper.parentTestShouldRunExecuted);
    }
}



================================================
FILE: jukito/src/test/java/org/jukito/ProviderBindingTest.java
================================================
/**
 * Copyright 2013 ArcBees Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.jukito;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;

import com.google.inject.Inject;
import com.google.inject.Provider;

import static junit.framework.Assert.assertNotNull;

/**
 * Test which ensures that a class which is a provider may also be binded independently.
 */
@RunWith(JukitoRunner.class)
public class ProviderBindingTest {

    /**
     * Guice test module.
     */
    public static class Module extends JukitoModule {
        @Override
        protected void configureTest() {
            bind(ServiceAndProvider.class);
            bind(MyService.class).toP
Download .txt
gitextract_98m20j73/

├── .gitignore
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── codequality/
│   ├── checkstyle.xml
│   ├── opensource.java.header
│   └── suppressions.xml
├── jukito/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── org/
│       │           └── jukito/
│       │               ├── All.java
│       │               ├── BindingsCollector.java
│       │               ├── Description.java
│       │               ├── EnvironmentDependentModules.java
│       │               ├── GuiceUtils.java
│       │               ├── InjectedAfterStatements.java
│       │               ├── InjectedBeforeStatements.java
│       │               ├── InjectedFrameworkMethod.java
│       │               ├── InjectedStatement.java
│       │               ├── JukitoInternal.java
│       │               ├── JukitoModule.java
│       │               ├── JukitoRunner.java
│       │               ├── MockProvider.java
│       │               ├── MockitoUsageValidator.java
│       │               ├── NamedUniqueAnnotations.java
│       │               ├── SpyImmutableInstanceProvider.java
│       │               ├── SpyProvider.java
│       │               ├── TestEagerSingleton.java
│       │               ├── TestMockSingleton.java
│       │               ├── TestModule.java
│       │               ├── TestScope.java
│       │               ├── TestSingleton.java
│       │               └── UseModules.java
│       └── test/
│           └── java/
│               └── org/
│                   └── jukito/
│                       ├── AllAnnotationTest.java
│                       ├── AllNamedAnnotationTest.java
│                       ├── AssistedInjectTest.java
│                       ├── AutoBindMocksDisabledTest.java
│                       ├── BindAnnotatedConcreteClassesTest.java
│                       ├── BindSpyInstanceTest.java
│                       ├── BindSpyTest.java
│                       ├── BindingToProviderTest.java
│                       ├── EDRunner.java
│                       ├── EnvironmentDependentComponent.java
│                       ├── ExternalSingleton.java
│                       ├── ForceMockTest.java
│                       ├── GeneralTest.java
│                       ├── InnerClassTest.java
│                       ├── InstallTest.java
│                       ├── ModuleWithProvidesMethods.java
│                       ├── NoModuleTest.java
│                       ├── OldStyleAssistedInjectTest.java
│                       ├── OneHundred.java
│                       ├── ParentClassInnerClassModuleDiscoveryTest.java
│                       ├── ParentTestClassBase.java
│                       ├── ParentTestClassTest.java
│                       ├── ProviderBindingTest.java
│                       ├── ProviderTest.java
│                       ├── ProvidesMethodTest.java
│                       ├── ReportWriterTest.java
│                       ├── RequestInjectionTest.java
│                       ├── RequestStaticInjectionTest.java
│                       ├── RespectProvidesAnnotationInModuleTest.java
│                       ├── RespectTestScopeWhenUsingAbstractModuleTest.java
│                       ├── SampleParentTestClassWithInnerTestModule.java
│                       ├── SingletonTest.java
│                       ├── SomeCoreComponent.java
│                       ├── SomeTestClass.java
│                       ├── TestTestDescriptions.java
│                       ├── TransitiveDependencyTest.java
│                       ├── UseModulesTest.java
│                       ├── Value3.java
│                       └── environmentdependent/
│                           ├── DesktopModule.java
│                           ├── EnvironmentDependentModulesTest.java
│                           ├── MobileModule.java
│                           └── TabletModule.java
├── jukito-samples/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── org/
│       │           └── jukito/
│       │               └── samples/
│       │                   ├── Car.java
│       │                   ├── DieselEngine.java
│       │                   ├── Engine.java
│       │                   ├── FordMustang.java
│       │                   ├── PetrolEngine.java
│       │                   └── modules/
│       │                       ├── DieselLineModule.java
│       │                       └── PetrolLineModule.java
│       └── test/
│           └── java/
│               └── org/
│                   └── jukito/
│                       └── samples/
│                           ├── FordMustangTest.java
│                           ├── FordMustangTest2.java
│                           └── FordMustangTest3.java
└── pom.xml
Download .txt
SYMBOL INDEX (777 symbols across 65 files)

FILE: jukito-samples/src/main/java/org/jukito/samples/Car.java
  class Car (line 19) | public abstract class Car {
    method Car (line 22) | public Car(Engine engine) {
    method startEngine (line 26) | public void startEngine() {
    method getEngine (line 30) | public Engine getEngine() {

FILE: jukito-samples/src/main/java/org/jukito/samples/DieselEngine.java
  class DieselEngine (line 19) | public class DieselEngine implements Engine {
    method initiateIgnition (line 20) | @Override

FILE: jukito-samples/src/main/java/org/jukito/samples/Engine.java
  type Engine (line 19) | public interface Engine {
    method initiateIgnition (line 20) | void initiateIgnition();

FILE: jukito-samples/src/main/java/org/jukito/samples/FordMustang.java
  class FordMustang (line 21) | public class FordMustang extends Car {
    method FordMustang (line 22) | @Inject

FILE: jukito-samples/src/main/java/org/jukito/samples/PetrolEngine.java
  class PetrolEngine (line 19) | public class PetrolEngine implements Engine {
    method initiateIgnition (line 20) | @Override

FILE: jukito-samples/src/main/java/org/jukito/samples/modules/DieselLineModule.java
  class DieselLineModule (line 24) | public class DieselLineModule extends AbstractModule {
    method configure (line 25) | @Override

FILE: jukito-samples/src/main/java/org/jukito/samples/modules/PetrolLineModule.java
  class PetrolLineModule (line 24) | public class PetrolLineModule extends AbstractModule {
    method configure (line 25) | @Override

FILE: jukito-samples/src/test/java/org/jukito/samples/FordMustangTest.java
  class FordMustangTest (line 30) | @RunWith(JukitoRunner.class)
    method shouldInitiateIgnitionWhenCarStart (line 35) | @Test

FILE: jukito-samples/src/test/java/org/jukito/samples/FordMustangTest2.java
  class FordMustangTest2 (line 31) | @RunWith(JukitoRunner.class)
    method shouldInitiateIgnitionWhenCarStart (line 36) | @Test
    class A (line 47) | public static class A extends JukitoModule {
      method configureTest (line 48) | @Override

FILE: jukito-samples/src/test/java/org/jukito/samples/FordMustangTest3.java
  class FordMustangTest3 (line 32) | @RunWith(JukitoRunner.class)
    method shouldInitiateIgnitionWhenCarStart (line 37) | @Test
    class A (line 51) | public static class A extends JukitoModule {
      method configureTest (line 52) | @Override

FILE: jukito/src/main/java/org/jukito/BindingsCollector.java
  class BindingsCollector (line 51) | public class BindingsCollector {
    class BindingInfo (line 56) | public static class BindingInfo {
      method create (line 63) | public static BindingInfo create(Binding<?> binding, Key<?> boundKey,
      method create (line 73) | public static BindingInfo create(Key<?> boundKey) {
    method BindingsCollector (line 85) | BindingsCollector(AbstractModule module) {
    method collectBindings (line 89) | public void collectBindings() {
    method getBindingsObserved (line 96) | public List<BindingInfo> getBindingsObserved() {
    class GuiceElementVisitor (line 103) | public class GuiceElementVisitor extends DefaultElementVisitor<Void> {
      method visitElements (line 105) | private void visitElements(List<Element> elements) {
      method visit (line 111) | @Override
      method visit (line 118) | @SuppressWarnings("unchecked")
      method visit (line 135) | @Override
      method visit (line 144) | @Override
      method addInjectionPointDependencies (line 150) | private void addInjectionPointDependencies(InjectionPoint injectionP...
    class GuiceBindingVisitor (line 167) | public class GuiceBindingVisitor<T> extends DefaultBindingTargetVisito...
      method addBindingInfo (line 169) | protected Void addBindingInfo(Binding<? extends T> binding, Key<?> b...
      method addBinding (line 174) | private Void addBinding(Binding<? extends T> binding) {
      method addBindingKey (line 178) | private Void addBindingKey(Binding<? extends T> binding, Key<?> boun...
      method addBindingInstance (line 182) | private Void addBindingInstance(Binding<? extends T> binding, Object...
      method visit (line 186) | @Override
      method visit (line 191) | @Override
      method visit (line 196) | @Override
      method visit (line 202) | @Override
      method visit (line 207) | @Override
      method visit (line 212) | @Override
      method visit (line 217) | @Override
      method visit (line 222) | @Override
    class GuicePrivateBindingVisitor (line 232) | public class GuicePrivateBindingVisitor<T> extends GuiceBindingVisitor...
      method visit (line 234) | @Override
    class GuiceScopingVisitor (line 243) | public static class GuiceScopingVisitor extends DefaultBindingScopingV...
      method visitEagerSingleton (line 245) | @Override
      method visitScope (line 250) | @Override
      method visitScopeAnnotation (line 255) | @Override

FILE: jukito/src/main/java/org/jukito/GuiceUtils.java
  class GuiceUtils (line 40) | public class GuiceUtils {
    method isProvider (line 42) | public static boolean isProvider(Key<?> key) {
    method getProvidedType (line 46) | @SuppressWarnings("unchecked")
    method getProvidedKey (line 68) | public static <T> Key<T> getProvidedKey(Key<Provider<T>> key,
    method ensureProvidedKey (line 81) | @SuppressWarnings("unchecked")
    method getMethodKeys (line 93) | public static List<Key<?>> getMethodKeys(Method method, Errors errors) {

FILE: jukito/src/main/java/org/jukito/InjectedAfterStatements.java
  class InjectedAfterStatements (line 33) | public class InjectedAfterStatements extends Statement {
    method InjectedAfterStatements (line 38) | public InjectedAfterStatements(Statement prev, List<FrameworkMethod> a...
    method evaluate (line 47) | @Override

FILE: jukito/src/main/java/org/jukito/InjectedBeforeStatements.java
  class InjectedBeforeStatements (line 32) | public class InjectedBeforeStatements extends Statement {
    method InjectedBeforeStatements (line 37) | public InjectedBeforeStatements(Statement next, List<FrameworkMethod> ...
    method evaluate (line 46) | @Override

FILE: jukito/src/main/java/org/jukito/InjectedFrameworkMethod.java
  class InjectedFrameworkMethod (line 30) | public class InjectedFrameworkMethod extends FrameworkMethod {
    method InjectedFrameworkMethod (line 34) | public InjectedFrameworkMethod(Method method) {
    method InjectedFrameworkMethod (line 39) | public InjectedFrameworkMethod(Method method, List<Binding<?>> binding...
    method getBindingsToUseForParameters (line 44) | public List<Binding<?>> getBindingsToUseForParameters() {

FILE: jukito/src/main/java/org/jukito/InjectedStatement.java
  class InjectedStatement (line 38) | class InjectedStatement extends Statement {
    method InjectedStatement (line 44) | InjectedStatement(FrameworkMethod method, Object test, Injector inject...
    method evaluate (line 50) | @Override

FILE: jukito/src/main/java/org/jukito/JukitoModule.java
  class JukitoModule (line 64) | public abstract class JukitoModule extends TestModule {
    method JukitoModule (line 73) | public JukitoModule() {
    method setBindingsObserved (line 92) | public void setBindingsObserved(List<BindingInfo> bindingsObserved) {
    method forceMock (line 104) | protected void forceMock(Class<?> klass) {
    method configure (line 108) | @Override
    method isInnerClass (line 216) | private boolean isInnerClass(Class<?> rawType) {
    method bindKeyToInstance (line 220) | @SuppressWarnings("unchecked")
    method addNeededKey (line 225) | private void addNeededKey(Set<Key<?>> keysObserved, Set<Key<?>> keysNe...
    method bindIfConcrete (line 231) | private <T> void bindIfConcrete(Set<Key<?>> keysObserved,
    method canBeInjected (line 250) | private boolean canBeInjected(TypeLiteral<?> type) {
    method isAssistedInjection (line 263) | private boolean isAssistedInjection(Key<?> key) {
    method shouldForceMock (line 268) | private boolean shouldForceMock(Class<?> klass) {
    method isInstantiable (line 297) | private boolean isInstantiable(Class<?> klass) {
    method isPrimitive (line 301) | private boolean isPrimitive(Class<?> klass) {
    method getDummyInstanceOfPrimitiveType (line 305) | private Object getDummyInstanceOfPrimitiveType(Class<?> klass) {
    method isCoreGuiceType (line 318) | private boolean isCoreGuiceType(Class<?> klass) {
    method addDependencies (line 326) | private <T> void addDependencies(Key<T> key, Set<Key<?>> keysObserved,
    method addInjectionPointDependencies (line 341) | private void addInjectionPointDependencies(InjectionPoint injectionPoint,
    method addKeyDependency (line 353) | private void addKeyDependency(Key<?> key, Set<Key<?>> keysObserved,
    method getReportWriter (line 377) | public Writer getReportWriter() {
    method printReport (line 386) | public void printReport(List<BindingInfo> allBindings) {
    method outputBindings (line 412) | private Set<Key<?>> outputBindings(Writer reportWriter, List<BindingIn...

FILE: jukito/src/main/java/org/jukito/JukitoRunner.java
  class JukitoRunner (line 62) | public class JukitoRunner extends BlockJUnit4ClassRunner {
    method JukitoRunner (line 66) | public JukitoRunner(Class<?> klass) throws InitializationError,
    method JukitoRunner (line 72) | public JukitoRunner(Class<?> klass, Injector injector) throws Initiali...
    method createInjector (line 86) | protected Injector createInjector(TestModule testModule) {
    method ensureInjector (line 90) | private void ensureInjector()
    method getTestModule (line 118) | private TestModule getTestModule(Class<?> testClass) throws Instantiat...
    method getUseModuleClasses (line 151) | private Set<Class<? extends Module>> getUseModuleClasses(Class<?> test...
    method getInnerClassModule (line 164) | private TestModule getInnerClassModule(Class<?> testClass)
    method getAutoBindMocksValue (line 178) | private boolean getAutoBindMocksValue(Class<?> testClass) {
    method createJukitoModule (line 192) | private TestModule createJukitoModule(final Iterable<Class<? extends M...
    method run (line 223) | @Override
    method createTest (line 230) | @Override
    method methodInvoker (line 237) | @Override
    method withBefores (line 242) | @Override
    method withAfters (line 256) | @Override
    method computeTestMethods (line 270) | @Override
    method testName (line 302) | @Override
    method getBindingsForParameterWithAllAnnotation (line 319) | private List<Binding<?>> getBindingsForParameterWithAllAnnotation(All ...
    method addAllBindingAssignations (line 348) | private void addAllBindingAssignations(
    method instantiateEagerTestSingletons (line 378) | private void instantiateEagerTestSingletons() {
    method validateInstanceMethods (line 404) | @Override
    method validateTestMethods (line 419) | @Override
    method validatePublicVoidMethods (line 433) | private void validatePublicVoidMethods(Class<? extends Annotation> ann...
    method getInjector (line 447) | protected Injector getInjector() {

FILE: jukito/src/main/java/org/jukito/MockProvider.java
  class MockProvider (line 34) | public class MockProvider<T> implements Provider<T> {
    method MockProvider (line 43) | public MockProvider(Class<T> classToProvide) {
    method get (line 47) | @Override

FILE: jukito/src/main/java/org/jukito/MockitoUsageValidator.java
  class MockitoUsageValidator (line 24) | public class MockitoUsageValidator extends RunListener {
    method MockitoUsageValidator (line 27) | public MockitoUsageValidator(RunNotifier notifier) {
    method testFinished (line 31) | @Override

FILE: jukito/src/main/java/org/jukito/NamedUniqueAnnotations.java
  class NamedUniqueAnnotations (line 30) | class NamedUniqueAnnotations {
    method matches (line 40) | public static boolean matches(String bindingName, java.lang.annotation...
    method create (line 53) | public static Annotation create(String name) {
    class InternalImpl (line 67) | private static class InternalImpl implements Internal {
      method InternalImpl (line 71) | InternalImpl(int value, String name) {
      method value (line 76) | public int value() {
      method name (line 80) | public String name() {
      method annotationType (line 84) | public Class<? extends Annotation> annotationType() {
      method toString (line 88) | @Override
      method equals (line 93) | @Override
      method hashCode (line 105) | @Override

FILE: jukito/src/main/java/org/jukito/SpyImmutableInstanceProvider.java
  class SpyImmutableInstanceProvider (line 33) | class SpyImmutableInstanceProvider<T> implements Provider<T> {
    method SpyImmutableInstanceProvider (line 45) | SpyImmutableInstanceProvider(T instance) {
    method get (line 52) | @Override

FILE: jukito/src/main/java/org/jukito/SpyProvider.java
  class SpyProvider (line 40) | class SpyProvider<T> implements Provider<T>, HasDependencies {
    method SpyProvider (line 55) | SpyProvider(Provider<T> rawProvider, Key<T> relayingKey) {
    method get (line 60) | @Override
    method getDependencies (line 65) | @Override

FILE: jukito/src/main/java/org/jukito/TestModule.java
  class TestModule (line 35) | public abstract class TestModule extends AbstractModule {
    method setTestClass (line 44) | public void setTestClass(Class<?> testClass) {
    method configure (line 48) | @Override
    method bindScopes (line 54) | protected void bindScopes() {
    method configureTest (line 62) | protected abstract void configureTest();
    method bindMock (line 72) | protected <T> ScopedBindingBuilder bindMock(Class<T> klass) {
    method bindMock (line 85) | protected <T> ScopedBindingBuilder bindMock(
    method bindSpy (line 99) | protected <T> ScopedBindingBuilder bindSpy(Class<T> klass) {
    method bindSpy (line 112) | protected <T> ScopedBindingBuilder bindSpy(
    method bindSpy (line 130) | protected <T> ScopedBindingBuilder bindSpy(Class<T> klass, T instance) {
    method bindSpy (line 148) | protected <T> ScopedBindingBuilder bindSpy(
    method bindNamedMock (line 163) | protected <T> ScopedBindingBuilder bindNamedMock(Class<T> klass, Strin...
    method bindNamedMock (line 177) | protected <T> ScopedBindingBuilder bindNamedMock(TypeLiteral<T> typeLi...
    method bindNamedSpy (line 193) | protected <T> ScopedBindingBuilder bindNamedSpy(Class<T> klass, String...
    method bindNamedSpy (line 208) | protected <T> ScopedBindingBuilder bindNamedSpy(TypeLiteral<T> typeLit...
    method bindNamedSpy (line 226) | protected <T> ScopedBindingBuilder bindNamedSpy(Class<T> klass, T inst...
    method bindNamedSpy (line 244) | protected <T> ScopedBindingBuilder bindNamedSpy(TypeLiteral<T> typeLit...
    method bindNewMockProvider (line 249) | @SuppressWarnings("unchecked")
    method bindNewSpyProvider (line 255) | @SuppressWarnings("unchecked")
    method bindNewSpyImmutableInstanceProvider (line 264) | private <T> ScopedBindingBuilder bindNewSpyImmutableInstanceProvider(K...
    method bindManyInstances (line 283) | protected <T, V extends T> void bindManyInstances(Class<T> clazz, V......
    method bindManyNamedInstances (line 304) | protected <T, V extends T> void bindManyNamedInstances(Class<T> clazz,...
    method bindManyInstances (line 325) | protected <T, V extends T> void bindManyInstances(TypeLiteral<T> type,...
    method bindManyNamedInstances (line 346) | protected <T, V extends T> void bindManyNamedInstances(TypeLiteral<T> ...
    method bindMany (line 362) | protected <T> void bindMany(Class<T> clazz, Class<? extends T>... boun...
    method bindManyNamed (line 378) | protected <T> void bindManyNamed(Class<T> clazz, String name, Class<? ...
    method bindMany (line 394) | protected <T> void bindMany(TypeLiteral<T> type, TypeLiteral<? extends...
    method bindManyNamed (line 410) | protected <T> void bindManyNamed(TypeLiteral<T> type, String name,
    method bindNamed (line 425) | protected <T> LinkedBindingBuilder<T> bindNamed(Class<T> klass, String...
    method bindNamed (line 437) | protected <T> LinkedBindingBuilder<T> bindNamed(TypeLiteral<T> typeLit...

FILE: jukito/src/main/java/org/jukito/TestScope.java
  class TestScope (line 32) | public class TestScope {
    class Singleton (line 34) | private static class Singleton implements Scope {
      method Singleton (line 39) | private Singleton(String simpleName) {
      method clear (line 43) | public void clear() {
      method scope (line 47) | @Override
      method toString (line 64) | public String toString() {
    method clear (line 91) | public static void clear() {

FILE: jukito/src/test/java/org/jukito/AllAnnotationTest.java
  class AllAnnotationTest (line 34) | @RunWith(JukitoRunner.class)
    class Module (line 40) | static class Module extends JukitoModule {
      method configureTest (line 41) | @SuppressWarnings("unchecked")
    type TestData (line 52) | interface TestData {
      method getData (line 53) | String getData();
    class TestDataA (line 56) | static class TestDataA implements TestData {
      method getData (line 57) | public String getData() {
    class TestDataB (line 62) | static class TestDataB implements TestData {
      method getData (line 63) | public String getData() {
    class TestDataInstance (line 68) | static class TestDataInstance {
      method TestDataInstance (line 71) | TestDataInstance(String data) {
      method getData (line 75) | public String getData() {
    type Node (line 80) | interface Node {
    class NodeA (line 83) | static class NodeA implements Node {
    class Bookkeeper (line 90) | private static class Bookkeeper {
    method testAllWithInstance (line 96) | @Test
    method testAllWithClass (line 101) | @Test
    method testAllWithClassInstance (line 106) | @Test
    method checkBookkeeper (line 111) | @AfterClass
    method testAllDoesNotIncludeMock (line 132) | @Test

FILE: jukito/src/test/java/org/jukito/AllNamedAnnotationTest.java
  class AllNamedAnnotationTest (line 32) | @RunWith(JukitoRunner.class)
    class Module (line 38) | static class Module extends JukitoModule {
      method configureTest (line 39) | @SuppressWarnings("unchecked")
    type TestData (line 55) | interface TestData {
      method getData (line 56) | String getData();
    class TestDataA (line 59) | static class TestDataA implements TestData {
      method getData (line 60) | public String getData() {
    class TestDataB (line 65) | static class TestDataB implements TestData {
      method getData (line 66) | public String getData() {
    class TestDataC (line 71) | static class TestDataC implements TestData {
      method getData (line 72) | public String getData() {
    class TestDataD (line 77) | static class TestDataD implements TestData {
      method getData (line 78) | public String getData() {
    class TestDataInstance (line 83) | static class TestDataInstance {
      method TestDataInstance (line 86) | TestDataInstance(String data) {
      method getData (line 90) | public String getData() {
    class Bookkeeper (line 99) | private static class Bookkeeper {
    method testAllWithNamedInstance (line 111) | @Test
    method testAllWithNamedClass (line 116) | @Test
    method testAllWithNamedClassInstance (line 121) | @Test
    method testAllWithInstance (line 127) | @Test
    method testAllWithClass (line 132) | @Test
    method testAllWithClassInstance (line 137) | @Test
    method testAllWithNullAsName (line 142) | @Test
    method checkBookkeeper (line 147) | @AfterClass

FILE: jukito/src/test/java/org/jukito/AssistedInjectTest.java
  class AssistedInjectTest (line 41) | @RunWith(JukitoRunner.class)
    class Module (line 47) | static class Module extends JukitoModule {
      method configureTest (line 48) | @Override
    type PaymentFactory (line 58) | interface PaymentFactory {
      method create (line 59) | Payment create(Date startDate, int amount);
    type Payment (line 62) | interface Payment {
      method format (line 63) | String format();
    class RealPayment (line 66) | static class RealPayment implements Payment {
      method RealPayment (line 71) | @Inject
      method format (line 78) | @Override
    type LocaleInfo (line 94) | interface LocaleInfo {
      method getMoneySign (line 95) | String getMoneySign();
      method isMoneySignBefore (line 97) | boolean isMoneySignBefore();
    type StarFactory (line 100) | interface StarFactory {
      method create (line 101) | Star create(String name, double mass);
    type Star (line 104) | interface Star {
      method getGravitationalConstant (line 105) | double getGravitationalConstant();
      method getMass (line 107) | double getMass();
      method getName (line 109) | String getName();
    class StarImpl (line 112) | static class StarImpl implements Star {
      method StarImpl (line 117) | @Inject
      method getGravitationalConstant (line 125) | @Override
      method getMass (line 130) | @Override
      method getName (line 135) | @Override
    method setup (line 144) | @Before
    method testFactory (line 150) | @Test
    method testFactoryWithInjectedConstant (line 163) | @Test

FILE: jukito/src/test/java/org/jukito/AutoBindMocksDisabledTest.java
  class AutoBindMocksDisabledTest (line 33) | @RunWith(JukitoRunner.class)
    class MyModule (line 40) | public static final class MyModule extends PrivateModule {
      method configure (line 42) | @Override
    type SomeInterface (line 53) | public interface SomeInterface {
      method doSomething (line 54) | void doSomething();
    class NotAMock (line 61) | public static final class NotAMock implements SomeInterface {
      method doSomething (line 63) | @Override
    class ExposedClass (line 72) | public static final class ExposedClass {
      method ExposedClass (line 76) | @Inject
      method getInstance (line 81) | SomeInterface getInstance() {
    method testSomething (line 86) | @Test

FILE: jukito/src/test/java/org/jukito/BindAnnotatedConcreteClassesTest.java
  class BindAnnotatedConcreteClassesTest (line 31) | @RunWith(JukitoRunner.class)
    class Module (line 37) | static class Module extends JukitoModule {
      method configureTest (line 38) | @Override
    class ConcreteClass (line 49) | static class ConcreteClass {
    class SubConcreteClass (line 52) | static class SubConcreteClass extends ConcreteClass {
    class SubSubConcreteClass (line 55) | static class SubSubConcreteClass extends ConcreteClass {
    method testConcreteClassBoundToDifferentSingletons (line 58) | @Test
    method testConcreteClassBoundToSameSingleton (line 65) | @Test
    method testConcreteClassNoBoundAsSingleton (line 72) | @Test

FILE: jukito/src/test/java/org/jukito/BindSpyInstanceTest.java
  class BindSpyInstanceTest (line 29) | @RunWith(JukitoRunner.class)
    class Module (line 35) | static class Module extends JukitoModule {
      method configureTest (line 36) | @Override
    class SimpleClass (line 42) | static class SimpleClass {
      method SimpleClass (line 45) | @SuppressWarnings("unused")
      method SimpleClass (line 50) | SimpleClass(String arg0) {
      method getVal (line 54) | String getVal() {
    method testOneInvocation (line 59) | @Test
    method testNeverInvoked (line 68) | @Test

FILE: jukito/src/test/java/org/jukito/BindSpyTest.java
  class BindSpyTest (line 32) | @RunWith(JukitoRunner.class)
    class Module (line 38) | static class Module extends JukitoModule {
      method configureTest (line 39) | @Override
    type CompositionMockA (line 45) | interface CompositionMockA {
      method test (line 46) | String test();
    type CompositionMockB (line 49) | interface CompositionMockB {
      method test (line 50) | String test();
    class SimpleClass (line 53) | static class SimpleClass {
      method SimpleClass (line 59) | @Inject
      method callTestMethodOnMock (line 64) | String callTestMethodOnMock() {
    method testStubbingSpiedInstance (line 76) | @Test
    method testNotStubbingSpiedInstance (line 90) | @Test

FILE: jukito/src/test/java/org/jukito/BindingToProviderTest.java
  class BindingToProviderTest (line 32) | @RunWith(JukitoRunner.class)
    class MyModule (line 38) | public static class MyModule extends JukitoModule {
      method getObject (line 39) | @Provides
      method configureTest (line 44) | @Override
    class MyClass (line 50) | static class MyClass {
      method MyClass (line 53) | MyClass(String string) {
      method getString (line 57) | String getString() {
    method foo (line 62) | @Test

FILE: jukito/src/test/java/org/jukito/EDRunner.java
  class EDRunner (line 36) | public class EDRunner extends ParentRunner {
    method EDRunner (line 39) | public EDRunner(Class<?> testClass) throws Exception {
    method createJukitoRunners (line 44) | public List<Runner> createJukitoRunners(Class<?> testClass) throws Exc...
    method calculateInjectors (line 55) | protected List<Injector> calculateInjectors(Class<?> testClass)
    method getChildren (line 74) | @Override
    method describeChild (line 79) | @Override
    method runChild (line 84) | @Override
    method buildInjector (line 89) | private Injector buildInjector(Class<? extends Module> edModuleClazz, ...
    method getDeclaredModulesForTest (line 119) | private Module[] getDeclaredModulesForTest(Class<?> testClass) {

FILE: jukito/src/test/java/org/jukito/EnvironmentDependentComponent.java
  type EnvironmentDependentComponent (line 22) | public interface EnvironmentDependentComponent {
    method hello (line 23) | void hello();

FILE: jukito/src/test/java/org/jukito/ExternalSingleton.java
  class ExternalSingleton (line 24) | @Singleton

FILE: jukito/src/test/java/org/jukito/ForceMockTest.java
  class ForceMockTest (line 29) | @RunWith(JukitoRunner.class)
    class Module (line 35) | static class Module extends JukitoModule {
      method configureTest (line 36) | @Override
    type Base1 (line 44) | interface Base1 {
      method t1 (line 45) | int t1();
    class Child11 (line 48) | static class Child11 implements Base1 {
      method t1 (line 49) | public int t1() {
    class Child111 (line 54) | static class Child111 extends Child11 {
      method t1 (line 55) | public int t1() {
    class Child12 (line 60) | static class Child12 implements Base1 {
      method t1 (line 61) | public int t1() {
    type Base2 (line 66) | interface Base2 {
      method t2 (line 67) | int t2();
    class Child21 (line 70) | static class Child21 implements Base2 {
      method t2 (line 71) | public int t2() {
    class Child211 (line 76) | static class Child211 extends Child21 {
      method t2 (line 77) | public int t2() {
    class Child22 (line 82) | static class Child22 implements Base2 {
      method t2 (line 83) | public int t2() {
    type Base3 (line 88) | interface Base3 {
      method t3 (line 89) | int t3();
    class Child31 (line 92) | static class Child31 implements Base3 {
      method t3 (line 93) | public int t3() {
    class Child311 (line 98) | static class Child311 extends Child31 {
      method t3 (line 99) | public int t3() {
    method injectForceMock (line 104) | @Test

FILE: jukito/src/test/java/org/jukito/GeneralTest.java
  class GeneralTest (line 40) | @RunWith(JukitoRunner.class)
    class Module (line 45) | static class Module extends JukitoModule {
      method configureTest (line 46) | @Override
    type MyInteger (line 88) | interface MyInteger {
      method getValue (line 89) | int getValue();
    class MyIntegerImpl (line 92) | static class MyIntegerImpl implements MyInteger {
      method MyIntegerImpl (line 95) | MyIntegerImpl(int value) {
      method getValue (line 99) | @Override
    type MyEnum (line 105) | enum MyEnum {
    class TestClass (line 111) | static class TestClass {
      method TestClass (line 114) | @Inject
    class ParameterizedTestClass (line 120) | static class ParameterizedTestClass<T> {
      method ParameterizedTestClass (line 123) | @Inject
    class ParameterizedTestClassDouble (line 129) | static class ParameterizedTestClassDouble extends ParameterizedTestCla...
      method ParameterizedTestClassDouble (line 130) | @Inject
    class ParameterizedTestClassString (line 136) | public static class ParameterizedTestClassString extends Parameterized...
      method ParameterizedTestClassString (line 137) | ParameterizedTestClassString() {
      method ParameterizedTestClassString (line 141) | public ParameterizedTestClassString(@Named("HelloWorld") String valu...
    class TestClassWithMethodInjection (line 146) | static class TestClassWithMethodInjection {
      method TestClassWithMethodInjection (line 149) | @Inject
      method setValue (line 154) | @Inject
    type NonBoundInterface (line 160) | interface NonBoundInterface {
      method getValue (line 161) | int getValue();
    class TestClassWithOptionalInjection (line 164) | static class TestClassWithOptionalInjection {
      method TestClassWithOptionalInjection (line 167) | @Inject
      method setValue (line 172) | @Inject(optional = true)
    class UninstanciableClass (line 179) | static class UninstanciableClass {
      method UninstanciableClass (line 180) | private UninstanciableClass() {
      method getValue (line 183) | public int getValue() {
    class ClassWithUninstanciableDependency1 (line 188) | @TestMockSingleton
      method ClassWithUninstanciableDependency1 (line 192) | @Inject
      method getValue (line 197) | public int getValue() {
      method getDependency (line 201) | public UninstanciableClass getDependency() {
    class ClassWithUninstanciableDependency2 (line 206) | abstract static class ClassWithUninstanciableDependency2 {
      method ClassWithUninstanciableDependency2 (line 207) | @Inject
      method getValue (line 211) | public int getValue() {
    class ClassWithUninstanciableDependency3 (line 216) | static class ClassWithUninstanciableDependency3 {
      method ClassWithUninstanciableDependency3 (line 217) | @Inject
      method getValue (line 221) | public int getValue() {
    class MyMockProvider3b (line 226) | static class MyMockProvider3b extends MockProvider<ClassWithUninstanci...
      method MyMockProvider3b (line 227) | @Inject
    class MyMockProvider3c (line 233) | static class MyMockProvider3c extends MockProvider<ClassWithUninstanci...
      method MyMockProvider3c (line 234) | @Inject
    class TestGenericClassInjectedWithTypeLiteral (line 240) | static class TestGenericClassInjectedWithTypeLiteral<U> {
      method TestGenericClassInjectedWithTypeLiteral (line 243) | @Inject
      method getInjectedType (line 248) | public Class<? super U> getInjectedType() {
    method testConstantInjection (line 253) | @Test
    method testInjectBoundWithKeys (line 278) | @Test
    method testParameterizedInjection1 (line 290) | @Test
    method testParameterizedInjection2 (line 296) | @Test
    method testMethodInjection (line 302) | @Test
    method testOptionalInjection (line 308) | @Test
    method testInjectingMockShouldNotInstantiateDependencies1 (line 314) | @Test
    method testInjectingMockShouldNotInstantiateDependencies2 (line 321) | @Test
    method testInjectingMockShouldNotInstantiateDependencies3a (line 327) | @Test
    method testInjectingMockShouldNotInstantiateDependencies3b (line 333) | @Test
    method testInjectingMockShouldNotInstantiateDependencies3c (line 339) | @Test
    method testInjectingClassInjectedWithTypeLiteralShouldWork (line 345) | @Test
    method testInjectingTypeLiteralShouldWork (line 351) | @Test
    method testInjectingInjectorShouldWork (line 357) | @Test
    method testInjectingLoggerShouldWork (line 362) | @Test
    method testInjectingStageShouldWork (line 367) | @Test
    method testInjectingMembersInjectorShouldWork (line 372) | @Test
    method toConstructorInjectionShouldWork (line 377) | @Test

FILE: jukito/src/test/java/org/jukito/InnerClassTest.java
  class InnerClassTest (line 32) | @RunWith(JukitoRunner.class)
    class Module (line 37) | public static class Module extends JukitoModule {
      method configureTest (line 38) | @Override
    class InnerClass (line 47) | class InnerClass {
      method toString (line 51) | public String toString() {
    class StaticInnerClass (line 59) | static class StaticInnerClass {
      method toString (line 63) | public String toString() {
    method testInnerClass (line 73) | @Test(expected = ConfigurationException.class)
    method testStaticInnerClass (line 83) | @Test

FILE: jukito/src/test/java/org/jukito/InstallTest.java
  class InstallTest (line 34) | @RunWith(JukitoRunner.class)
    class Module (line 40) | static class Module extends JukitoModule {
      class FooModule (line 42) | public class FooModule extends AbstractModule {
        method configure (line 44) | @Override
      class BarModule (line 50) | public class BarModule extends AbstractModule {
        method configure (line 52) | @Override
      method configureTest (line 58) | @Override
    type Foo (line 66) | interface Foo {
      method calc (line 67) | int calc();
    class FooImpl (line 70) | static class FooImpl implements Foo {
      method FooImpl (line 75) | @Inject
      method calc (line 81) | @Override
    type Bar (line 87) | interface Bar {
      method calc (line 88) | int calc();
    class BarImpl (line 91) | static class BarImpl implements Bar {
      method calc (line 92) | @Override
    method setup (line 101) | @Before
    method installingModuleWorks (line 106) | @Test

FILE: jukito/src/test/java/org/jukito/ModuleWithProvidesMethods.java
  class ModuleWithProvidesMethods (line 26) | public class ModuleWithProvidesMethods extends AbstractModule {
    method create (line 28) | @Provides
    method configure (line 36) | @Override

FILE: jukito/src/test/java/org/jukito/NoModuleTest.java
  class NoModuleTest (line 28) | @RunWith(JukitoRunner.class)
    type MyMockSingleton (line 31) | interface MyMockSingleton {
      method dummy (line 32) | int dummy();
    type MyAnnotatedMockSingleton (line 35) | @TestMockSingleton
      method dummy (line 37) | int dummy();
    class MySingleton (line 40) | static class MySingleton {
    class MyAnnotatedSingleton (line 43) | @TestSingleton
    class MyAnnotatedEagerSingleton (line 47) | @TestEagerSingleton
    method testMockSingleton (line 51) | @Test
    method testAnnotatedMockSingleton (line 59) | @Test
    method testSingleton (line 68) | @Test
    method testAnnotatedSingleton (line 73) | @Test
    method testAnnotatedEagerSingleton (line 78) | @Test

FILE: jukito/src/test/java/org/jukito/OldStyleAssistedInjectTest.java
  class OldStyleAssistedInjectTest (line 33) | @SuppressWarnings("deprecation")
    class Module (line 39) | public static class Module extends JukitoModule {
      method configureTest (line 40) | @Override
    type PaymentFactory (line 57) | interface PaymentFactory {
      method create (line 58) | Payment create(int amount);
    type PaymentAmountFactory (line 61) | interface PaymentAmountFactory {
      method create (line 62) | Payment create(Amount amount);
    type Payment (line 65) | interface Payment {
      method getPayment (line 66) | String getPayment();
    class RealPayment1 (line 69) | static class RealPayment1 implements Payment {
      method RealPayment1 (line 73) | @Inject
      method getPayment (line 79) | @Override
    class RealPayment2 (line 85) | static class RealPayment2 implements Payment {
      method RealPayment2 (line 88) | @Inject
      method getPayment (line 93) | @Override
    type Amount (line 99) | interface Amount {
      method toString (line 100) | String toString();
    type Configuration (line 106) | interface Configuration {
      method shouldAlwaysHideAmounts (line 107) | boolean shouldAlwaysHideAmounts();
    class InjectedClass (line 112) | static class InjectedClass {
    class RealPaymentAmount (line 118) | static class RealPaymentAmount implements Payment {
      method RealPaymentAmount (line 123) | @Inject
      method getPayment (line 132) | @Override
    method shouldInjectFactoryInClass (line 145) | @Test
    method shouldInjectFactoryAsParameter (line 154) | @Test
    method shouldInjectFactoryWithInterfacesAsParameter (line 163) | @Test

FILE: jukito/src/test/java/org/jukito/ParentClassInnerClassModuleDiscoveryTest.java
  class ParentClassInnerClassModuleDiscoveryTest (line 29) | @RunWith(JukitoRunner.class)
    method afterClass (line 34) | @AfterClass
    method testSomething (line 39) | @Test

FILE: jukito/src/test/java/org/jukito/ParentTestClassBase.java
  class ParentTestClassBase (line 35) | @Ignore("Tests in this base class are not meant to be run independantly.")
    class SingletonDefinedInParent (line 41) | @TestSingleton
      method getValue (line 45) | public String getValue() {
    type MockSingletonDefinedInParent (line 53) | @TestMockSingleton
      method mockSingletonMethod (line 55) | void mockSingletonMethod();
    type DummyInterface (line 58) | interface DummyInterface {
      method getDummyValue (line 59) | String getDummyValue();
    type DummyInterfaceUsedOnlyInParent1 (line 62) | interface DummyInterfaceUsedOnlyInParent1 {
      method getDummyValue (line 63) | String getDummyValue();
    type DummyInterfaceUsedOnlyInParent2 (line 66) | interface DummyInterfaceUsedOnlyInParent2 {
      method getDummyValue (line 67) | String getDummyValue();
    type DummyInterfaceUsedOnlyInParent3 (line 70) | interface DummyInterfaceUsedOnlyInParent3 {
      method getDummyValue (line 71) | String getDummyValue();
    class DummyClassUsedOnlyInParent1 (line 74) | static class DummyClassUsedOnlyInParent1 {
    class DummyClassUsedOnlyInParent2 (line 77) | static class DummyClassUsedOnlyInParent2 {
    class DummyClassUsedOnlyInParent3 (line 80) | static class DummyClassUsedOnlyInParent3 {
    class Bookkeeper (line 92) | protected static class Bookkeeper {
    method parentTestShouldRun (line 96) | @Test
    method interfaceBoundInChildIsInjectedInParent (line 101) | @Test
    method interfaceBoundInChildIsInjectedInParentTestMethod (line 106) | @Test
    method interfaceUsedInParentTestMethodShouldBeMockedAsTestSingleton (line 112) | @Test
    method concreteClassUsedInParentTestMethodShouldBeBoundAsTestSingleton (line 121) | @Test
    method interfaceUsedInParentBeforeMethodShouldBeMockedAsTestSingleton (line 127) | @Before
    method concreteClassUsedInParentBeforeMethodShouldBeBoundAsTestSingleton (line 136) | @Before
    method interfaceUsedInParentAfterMethodShouldBeMockedAsTestSingleton (line 142) | @After
    method concreteClassUsedInParentAfterMethodShouldBeBoundAsTestSingleton (line 151) | @After

FILE: jukito/src/test/java/org/jukito/ParentTestClassTest.java
  class ParentTestClassTest (line 31) | @RunWith(JukitoRunner.class)
    class Module (line 37) | static class Module extends JukitoModule {
      method configureTest (line 38) | @Override
    class MyDummyClass (line 47) | static class MyDummyClass implements DummyInterface {
      method getDummyValue (line 48) | @Override
    method mockSingletonDefinedInParentShouldBeBoundAsAMock (line 54) | @Test
    method singletonDefinedInParentShouldBeBound (line 59) | @Test
    method checkBookkeeper (line 65) | @AfterClass

FILE: jukito/src/test/java/org/jukito/ProviderBindingTest.java
  class ProviderBindingTest (line 31) | @RunWith(JukitoRunner.class)
    class Module (line 37) | public static class Module extends JukitoModule {
      method configureTest (line 38) | @Override
    method shouldBeExecuted (line 45) | @Test
    type MyService (line 51) | interface MyService {
    class ServiceAndProvider (line 54) | static class ServiceAndProvider implements Provider<MyService> {
      method get (line 55) | @Override
      method doSomethingVeryImportant (line 60) | public void doSomethingVeryImportant() {
    class OtherService (line 65) | static class OtherService {

FILE: jukito/src/test/java/org/jukito/ProviderTest.java
  class ProviderTest (line 38) | @RunWith(JukitoRunner.class)
    class Module (line 44) | static class Module extends JukitoModule {
      method configureTest (line 45) | @Override
      method getProvidedViaMethod (line 68) | @Provides
    type Mock (line 74) | interface Mock {
    class Instance (line 77) | static class Instance {
      method Instance (line 78) | @Inject
    type Parent (line 83) | interface Parent {
      method getValue (line 84) | String getValue();
    class ChildA (line 87) | static class ChildA implements Parent {
      method getValue (line 88) | public String getValue() {
    type MockInChildB (line 93) | interface MockInChildB {
    type MockInProviderB (line 96) | interface MockInProviderB {
      method test (line 97) | void test();
    class ChildB (line 100) | static class ChildB implements Parent {
      method getValue (line 104) | public String getValue() {
    class ParentProviderABase (line 109) | abstract static class ParentProviderABase implements Provider<Parent> {
    class ParentProviderA (line 112) | static class ParentProviderA extends ParentProviderABase {
      method get (line 113) | @Override
    class ParentProviderB (line 119) | static class ParentProviderB implements Provider<Parent> {
      method ParentProviderB (line 122) | @Inject
      method get (line 131) | @Override
    class UninstanciableClass (line 137) | static class UninstanciableClass {
      method UninstanciableClass (line 138) | private UninstanciableClass() {
      method getValue (line 141) | public int getValue() {
    class MyMockProvider2 (line 146) | static class MyMockProvider2 extends MockProvider<UninstanciableClass> {
      method MyMockProvider2 (line 147) | @Inject
    class MyMockProvider3 (line 153) | static class MyMockProvider3 extends MockProvider<UninstanciableClass> {
      method MyMockProvider3 (line 154) | @Inject
    type DependencyShouldBeMocked1 (line 160) | interface DependencyShouldBeMocked1 {
      method getValue (line 161) | int getValue();
    class ClassWithMockedDependency1 (line 164) | static class ClassWithMockedDependency1 {
      method ClassWithMockedDependency1 (line 167) | @Inject
      method getDependency (line 172) | public DependencyShouldBeMocked1 getDependency() {
    class MyProvider1 (line 177) | static class MyProvider1 implements Provider<ClassWithMockedDependency...
      method MyProvider1 (line 180) | @Inject
      method get (line 185) | @Override
    type DependencyShouldBeMocked2 (line 191) | interface DependencyShouldBeMocked2 {
      method getValue (line 192) | int getValue();
    class ClassWithMockedDependency2 (line 195) | static class ClassWithMockedDependency2 {
      method ClassWithMockedDependency2 (line 198) | @Inject
      method getDependency (line 203) | public DependencyShouldBeMocked2 getDependency() {
    class MyProvider2 (line 208) | static class MyProvider2 implements Provider<ClassWithMockedDependency...
      method MyProvider2 (line 211) | @Inject
      method get (line 216) | @Override
    class ProvidedViaMethod (line 222) | static class ProvidedViaMethod {
      method ProvidedViaMethod (line 225) | ProvidedViaMethod(String value) {
    method mockSingletonProviderShouldReturnTheSameInstance (line 230) | @Test
    method mockNonSingletonProviderShouldNotReturnTheSameInstance (line 236) | @Test
    method singletonProvidedClassShouldReturnTheSameInstance (line 242) | @Test
    method singletonClassShouldNotReturnTheSameInstance (line 248) | @Test
    method nonSingletonProvidedClassShouldNotReturnTheSameInstance (line 254) | @Test
    method nonSingletonClassShouldNotReturnTheSameInstance (line 260) | @Test
    method bindingToProviderInstanceShouldWorkAndInject (line 266) | @Test
    method shouldInjectProviderBoundWithInstance (line 272) | @Test
    method shouldInjectProviderBoundWithClass (line 278) | @Test
    method shouldInjectProviderBoundWithKey (line 284) | @Test
    method shouldInjectProviderOfClassWithPrivateConstructor1 (line 290) | @Test
    method shouldInjectProviderOfClassWithPrivateConstructor2 (line 296) | @Test
    method shouldInjectProviderOfClassWithPrivateConstructor3 (line 302) | @Test
    method testInjectingProviderShouldInstantiateDependencies1 (line 308) | @Test
    method testInjectingProviderShouldInstantiateDependencies2 (line 314) | @Test
    method providesMethodShouldWork (line 320) | @Test

FILE: jukito/src/test/java/org/jukito/ProvidesMethodTest.java
  class ProvidesMethodTest (line 37) | @RunWith(JukitoRunner.class)
    class Module (line 43) | static class Module extends JukitoModule {
      method configureTest (line 44) | @Override
      method providesParent1 (line 53) | @Provides
      method providesParent2 (line 60) | @Provides
      method providesParent3 (line 70) | @Provides
      method providesUninstanciableClass2 (line 77) | @Provides
      method providesUninstanciableClass3 (line 84) | @Provides
      method providesClassWithMockedDependency1 (line 91) | @Provides
      method providesClassWithMockedDependency2 (line 98) | @Provides
      method aValue (line 105) | @Provides
      method anInteger (line 110) | @Provides
    type Mock (line 116) | interface Mock {
    class Instance (line 119) | static class Instance {
      method Instance (line 120) | @Inject
    type Parent (line 125) | interface Parent {
      method getValue (line 126) | String getValue();
    class ChildA (line 129) | static class ChildA implements Parent {
      method getValue (line 130) | public String getValue() {
    type MockInChildB (line 135) | interface MockInChildB {
    type MockInProviderB (line 138) | interface MockInProviderB {
      method test (line 139) | void test();
    class ChildB (line 142) | static class ChildB implements Parent {
      method getValue (line 146) | public String getValue() {
    class UninstanciableClass (line 151) | static class UninstanciableClass {
      method UninstanciableClass (line 152) | private UninstanciableClass() {
      method getValue (line 155) | public int getValue() {
    type DependencyShouldBeMocked1 (line 160) | interface DependencyShouldBeMocked1 {
      method getValue (line 161) | int getValue();
    class ClassWithMockedDependency1 (line 164) | static class ClassWithMockedDependency1 {
      method ClassWithMockedDependency1 (line 167) | @Inject
      method getDependency (line 172) | public DependencyShouldBeMocked1 getDependency() {
    type DependencyShouldBeMocked2 (line 177) | interface DependencyShouldBeMocked2 {
      method getValue (line 178) | int getValue();
    class ClassWithMockedDependency2 (line 181) | static class ClassWithMockedDependency2 {
      method ClassWithMockedDependency2 (line 184) | @Inject
      method getDependency (line 189) | public DependencyShouldBeMocked2 getDependency() {
    class Value (line 194) | static class Value {
      method Value (line 197) | Value(String string) {
    method mockSingletonProviderShouldReturnTheSameInstance (line 204) | @Test
    method mockNonSingletonProviderShouldNotReturnTheSameInstance (line 210) | @Test
    method singletonProvidedClassShouldReturnTheSameInstance (line 216) | @Test
    method singletonClassShouldNotReturnTheSameInstance (line 222) | @Test
    method nonSingletonProvidedClassShouldNotReturnTheSameInstance (line 228) | @Test
    method nonSingletonClassShouldNotReturnTheSameInstance (line 234) | @Test
    method bindingToProviderInstanceShouldWorkAndInject (line 240) | @Test
    method shouldInjectProviderBoundWithInstance (line 246) | @Test
    method shouldInjectProviderBoundWithClass (line 252) | @Test
    method shouldInjectProviderBoundWithKey (line 258) | @Test
    method shouldInjectProviderOfClassWithPrivateConstructor1 (line 264) | @Test
    method shouldInjectProviderOfClassWithPrivateConstructor2 (line 270) | @Test
    method shouldInjectProviderOfClassWithPrivateConstructor3 (line 276) | @Test
    method testInjectingProviderShouldInstantiateDependencies1 (line 282) | @Test
    method testInjectingProviderShouldInstantiateDependencies2 (line 288) | @Test
    method testProvidingConstants (line 294) | @Test

FILE: jukito/src/test/java/org/jukito/ReportWriterTest.java
  class ReportWriterTest (line 37) | @RunWith(JukitoRunner.class)
    class Module (line 43) | static class Module extends JukitoModule {
      method getReportWriter (line 47) | @Override
      method configureTest (line 52) | @Override
    class Resource1 (line 60) | @Singleton
    type Resource2 (line 64) | interface Resource2 {
    class Resource3 (line 67) | static class Resource3 {
      method Resource3 (line 72) | @Inject
      method setResource6 (line 76) | @Inject
    class Resource4 (line 81) | static class Resource4 {
    type Resource5 (line 84) | interface Resource5 {
    class Resource6 (line 87) | static class Resource6 {
    method ensureReport (line 95) | @Test
    method findBlock (line 128) | private Set<String> findBlock(String header, String text) {

FILE: jukito/src/test/java/org/jukito/RequestInjectionTest.java
  class RequestInjectionTest (line 30) | @RunWith(JukitoRunner.class)
    type Dummy (line 32) | interface Dummy {
    class RequestInjection (line 35) | static class RequestInjection {
      method getDummy (line 39) | public Dummy getDummy() {
    class Module (line 44) | static class Module extends JukitoModule {
      method configureTest (line 45) | @Override
    method dummyShouldBeMocked (line 55) | @Test

FILE: jukito/src/test/java/org/jukito/RequestStaticInjectionTest.java
  class RequestStaticInjectionTest (line 35) | @RunWith(JukitoRunner.class)
    type Dummy (line 37) | interface Dummy {
    class RequestStaticInjectionA (line 40) | static class RequestStaticInjectionA {
    class RequestStaticInjectionB (line 46) | static class RequestStaticInjectionB {
    class Module (line 51) | static class Module extends JukitoModule {
      method configureTest (line 52) | @Override
      method createDummy (line 58) | @Provides
    method dummyShouldNotBeMocked (line 66) | @Test
    method dummyShouldBeMocked (line 75) | @Test

FILE: jukito/src/test/java/org/jukito/RespectProvidesAnnotationInModuleTest.java
  class RespectProvidesAnnotationInModuleTest (line 27) | @RunWith(JukitoRunner.class)
    method shouldRespectProvidesAnnotationUsedInModule (line 29) | @Test
    class A (line 45) | public static class A extends JukitoModule {
      method configureTest (line 46) | @Override

FILE: jukito/src/test/java/org/jukito/RespectTestScopeWhenUsingAbstractModuleTest.java
  class RespectTestScopeWhenUsingAbstractModuleTest (line 33) | @RunWith(JukitoRunner.class)
    method shouldRespectTestSingletonAnnotationA (line 43) | @Test
    method shouldRespectTestSingletonsB (line 57) | @Test
    method shouldRespectTestSingletonsC (line 69) | @Test
    class A (line 84) | public static class A extends JukitoModule {
      method configureTest (line 85) | @Override

FILE: jukito/src/test/java/org/jukito/SampleParentTestClassWithInnerTestModule.java
  class SampleParentTestClassWithInnerTestModule (line 23) | public class SampleParentTestClassWithInnerTestModule {
    class MyModule (line 30) | public static final class MyModule extends JukitoModule {
      method configureTest (line 31) | @Override

FILE: jukito/src/test/java/org/jukito/SingletonTest.java
  class SingletonTest (line 36) | @RunWith(JukitoRunner.class)
    class Module (line 42) | static class Module extends JukitoModule {
      method configureTest (line 43) | @Override
    class Registry (line 51) | @TestSingleton
      method register (line 55) | public void register(Class<?> clazz) {
      method getCount (line 59) | public int getCount(Class<?> clazz) {
    class Bookkeeper (line 72) | private static class Bookkeeper {
    class MyEagerSingleton (line 83) | static class MyEagerSingleton {
      method MyEagerSingleton (line 84) | @Inject
    class MyTestEagerSingleton (line 94) | @TestEagerSingleton
      method MyTestEagerSingleton (line 96) | @Inject
    class MyTestSingleton (line 106) | @TestSingleton
      method MyTestSingleton (line 108) | @Inject
    type MyTestMockSingleton (line 118) | @TestMockSingleton
      method dummy (line 120) | void dummy();
    type MyTestMockSingletonBoundNonMock (line 127) | @TestMockSingleton
      method dummy (line 129) | void dummy();
    method onlyEagerSingletonShouldBeRegistered (line 135) | @Test
    method bothSingletonsShouldBeRegistered (line 140) | @Test
    method injectionOfMockShouldBeADifferentObject1 (line 146) | @Test
    method injectionOfMockShouldBeADifferentObject2 (line 152) | @Test
    method injectionOfSingletonMockExplicitelyBoundAsNonSingleton (line 158) | @Test
    method firstInjectionOfSingleton (line 167) | @Test
    method secondInjectionOfSingleton (line 172) | @Test
    method verifyNumberOfInstantiations (line 177) | @AfterClass

FILE: jukito/src/test/java/org/jukito/SomeCoreComponent.java
  class SomeCoreComponent (line 22) | public class SomeCoreComponent {
    method SomeCoreComponent (line 25) | public SomeCoreComponent(EnvironmentDependentComponent someComponent) {
    method run (line 29) | public void run() {

FILE: jukito/src/test/java/org/jukito/SomeTestClass.java
  class SomeTestClass (line 22) | public class SomeTestClass {
    method someInitMethod (line 23) | public void someInitMethod() {
    method crazyMethod (line 27) | public void crazyMethod() {

FILE: jukito/src/test/java/org/jukito/TestTestDescriptions.java
  class TestTestDescriptions (line 25) | @RunWith(JukitoRunner.class)
    method testA (line 27) | @Test
    method testB (line 37) | @Test
    method testWithoutDescription (line 48) | @Test

FILE: jukito/src/test/java/org/jukito/TransitiveDependencyTest.java
  class TransitiveDependencyTest (line 33) | @RunWith(JukitoRunner.class)
    class MyModule (line 36) | static class MyModule extends JukitoModule {
      method configureTest (line 37) | @Override
    type SubCollaborator (line 44) | interface SubCollaborator {
      method subCollaborate (line 45) | void subCollaborate();
    class Collaborator (line 48) | @TestEagerSingleton
      method Collaborator (line 52) | @Inject
    class Leader (line 58) | @TestEagerSingleton
      method Leader (line 62) | @Inject
    type MyInterface (line 68) | interface MyInterface {
      method getValue (line 69) | int getValue();
    class MyDependency (line 72) | static class MyDependency {
      method getValue (line 73) | public int getValue() {
    type MyDependentInterface (line 78) | interface MyDependentInterface {
    class MyInterfaceImpl (line 81) | static class MyInterfaceImpl implements MyInterface {
      method MyInterfaceImpl (line 84) | @Inject
      method getValue (line 90) | @Override
    type MyEnum (line 96) | enum MyEnum {
    class MyClassInjectedWithUnboundConstants (line 100) | static class MyClassInjectedWithUnboundConstants {
      method MyClassInjectedWithUnboundConstants (line 114) | @Inject
      method setAutoinit (line 123) | @Inject
      method setSensitivity (line 127) | @Inject
    method testDoubleDependency (line 132) | @Test
    method testDependencyFromInterface (line 137) | @Test
    method testDependencyOnUnboundConstants (line 142) | @Test

FILE: jukito/src/test/java/org/jukito/UseModulesTest.java
  class UseModulesTest (line 37) | @RunWith(JukitoRunner.class)
    type Abc (line 40) | interface Abc {
    type Def (line 43) | interface Def {
    type Ghj (line 46) | interface Ghj {
    type Klm (line 49) | interface Klm {
    class AbcImpl (line 52) | static class AbcImpl implements Abc {
    class DefImpl (line 55) | static class DefImpl implements Def {
    class AbcImpl2 (line 58) | static class AbcImpl2 implements Abc {
    class DefImpl2 (line 61) | static class DefImpl2 implements Def {
    class KlmImpl (line 64) | static class KlmImpl implements Klm {
    method testInjectionUsingMethodModules (line 67) | @Test
    method testInjectionWithExternalModules (line 74) | @Test
    method testAutoMockingForMissingBindings (line 81) | @Test
  class XyzModule (line 88) | class XyzModule extends AbstractModule {
    method configure (line 89) | @Override
  class UseModulesTestBase (line 96) | @UseModules({DefModule.class, KlmModule.class})
  class AbcModule (line 102) | class AbcModule extends AbstractModule {
    method configure (line 103) | @Override
  class DefModule (line 109) | class DefModule extends AbstractModule {
    method configure (line 110) | @Override
  class KlmModule (line 116) | class KlmModule extends AbstractModule {
    method configure (line 117) | @Override

FILE: jukito/src/test/java/org/jukito/environmentdependent/DesktopModule.java
  class DesktopModule (line 26) | public class DesktopModule extends AbstractModule {
    method configure (line 27) | @Override

FILE: jukito/src/test/java/org/jukito/environmentdependent/EnvironmentDependentModulesTest.java
  class EnvironmentDependentModulesTest (line 36) | @EnvironmentDependentModules({MobileModule.class, DesktopModule.class, T...
    method shouldRunAsManyTimesAsManyInjectorsWereCreated (line 40) | @Test
    class SomeCoreModule (line 48) | public static class SomeCoreModule extends AbstractModule {
      method createCalculator (line 49) | @Provides
      method configure (line 54) | @Override

FILE: jukito/src/test/java/org/jukito/environmentdependent/MobileModule.java
  class MobileModule (line 26) | public class MobileModule extends AbstractModule {
    method configure (line 27) | @Override

FILE: jukito/src/test/java/org/jukito/environmentdependent/TabletModule.java
  class TabletModule (line 26) | public class TabletModule extends AbstractModule {
    method configure (line 27) | @Override
Condensed preview — 85 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (290K chars).
[
  {
    "path": ".gitignore",
    "chars": 102,
    "preview": "gwt-unitCache\nwww-test\ntarget\n.project\n*.iml\n.settings\n.idea\n.classpath\n.gwt\nbin\nMETA-INF\n.checkstyle\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 15,
    "preview": "# Contributing\n"
  },
  {
    "path": "LICENSE.md",
    "chars": 123,
    "preview": "# License\n\nJukito is freely distributable under the [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0.html"
  },
  {
    "path": "README.md",
    "chars": 4059,
    "preview": "![Jukito](http://i.imgur.com/rSeHAEc.png \"Jukito\")\n\n### The combined power of JUnit, Guice and Mockito. Plus it sounds l"
  },
  {
    "path": "codequality/checkstyle.xml",
    "chars": 7701,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE module PUBLIC \"-//Puppy Crawl//DTD Check Configuration 1.3//EN\"\n       "
  },
  {
    "path": "codequality/opensource.java.header",
    "chars": 621,
    "preview": "/\\*\\*?\n \\* Copyright \\d{4} ArcBees Inc\\.\n \\*\n \\* Licensed under the Apache License, Version 2\\.0 \\(the \"License\"\\); you "
  },
  {
    "path": "codequality/suppressions.xml",
    "chars": 531,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE suppressions PUBLIC\n        \"-//Puppy Crawl//DTD Suppressions 1.1//EN\"\n"
  },
  {
    "path": "jukito/pom.xml",
    "chars": 2881,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:sc"
  },
  {
    "path": "jukito/src/main/java/org/jukito/All.java",
    "chars": 1946,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/main/java/org/jukito/BindingsCollector.java",
    "chars": 9099,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/main/java/org/jukito/Description.java",
    "chars": 996,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/main/java/org/jukito/EnvironmentDependentModules.java",
    "chars": 1190,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/main/java/org/jukito/GuiceUtils.java",
    "chars": 4298,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/main/java/org/jukito/InjectedAfterStatements.java",
    "chars": 2162,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/main/java/org/jukito/InjectedBeforeStatements.java",
    "chars": 1686,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/main/java/org/jukito/InjectedFrameworkMethod.java",
    "chars": 1502,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/main/java/org/jukito/InjectedStatement.java",
    "chars": 3920,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/main/java/org/jukito/JukitoInternal.java",
    "chars": 1102,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/main/java/org/jukito/JukitoModule.java",
    "chars": 18073,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/main/java/org/jukito/JukitoRunner.java",
    "chars": 17080,
    "preview": "/*\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * u"
  },
  {
    "path": "jukito/src/main/java/org/jukito/MockProvider.java",
    "chars": 1561,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/main/java/org/jukito/MockitoUsageValidator.java",
    "chars": 1306,
    "preview": "/*\n * Copyright 2017 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * u"
  },
  {
    "path": "jukito/src/main/java/org/jukito/NamedUniqueAnnotations.java",
    "chars": 3378,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/main/java/org/jukito/SpyImmutableInstanceProvider.java",
    "chars": 1744,
    "preview": "/**\n * Copyright 2014 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/main/java/org/jukito/SpyProvider.java",
    "chars": 2446,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/main/java/org/jukito/TestEagerSingleton.java",
    "chars": 1222,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/main/java/org/jukito/TestMockSingleton.java",
    "chars": 1143,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/main/java/org/jukito/TestModule.java",
    "chars": 19301,
    "preview": "/**\n * Copyright 2014 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/main/java/org/jukito/TestScope.java",
    "chars": 3040,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/main/java/org/jukito/TestSingleton.java",
    "chars": 1212,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/main/java/org/jukito/UseModules.java",
    "chars": 1867,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/AllAnnotationTest.java",
    "chars": 4341,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/AllNamedAnnotationTest.java",
    "chars": 9406,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/AssistedInjectTest.java",
    "chars": 4907,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/AutoBindMocksDisabledTest.java",
    "chars": 2640,
    "preview": "/*\n * Copyright 2017 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * u"
  },
  {
    "path": "jukito/src/test/java/org/jukito/BindAnnotatedConcreteClassesTest.java",
    "chars": 2390,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/BindSpyInstanceTest.java",
    "chars": 1758,
    "preview": "/**\n * Copyright 2014 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/BindSpyTest.java",
    "chars": 2483,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/BindingToProviderTest.java",
    "chars": 1675,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/EDRunner.java",
    "chars": 4450,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/EnvironmentDependentComponent.java",
    "chars": 785,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/ExternalSingleton.java",
    "chars": 774,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/ForceMockTest.java",
    "chars": 3051,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/GeneralTest.java",
    "chars": 12181,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/InnerClassTest.java",
    "chars": 2357,
    "preview": "/**\n * Copyright 2014 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/InstallTest.java",
    "chars": 2684,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/ModuleWithProvidesMethods.java",
    "chars": 1075,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/NoModuleTest.java",
    "chars": 2029,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/OldStyleAssistedInjectTest.java",
    "chars": 5188,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/OneHundred.java",
    "chars": 880,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/ParentClassInnerClassModuleDiscoveryTest.java",
    "chars": 1383,
    "preview": "/*\n * Copyright 2017 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * u"
  },
  {
    "path": "jukito/src/test/java/org/jukito/ParentTestClassBase.java",
    "chars": 4570,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/ParentTestClassTest.java",
    "chars": 2040,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/ProviderBindingTest.java",
    "chars": 1831,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/ProviderTest.java",
    "chars": 10041,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/ProvidesMethodTest.java",
    "chars": 8685,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/ReportWriterTest.java",
    "chars": 4584,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/RequestInjectionTest.java",
    "chars": 1489,
    "preview": "/**\n * Copyright 2014 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/RequestStaticInjectionTest.java",
    "chars": 2058,
    "preview": "/**\n * Copyright 2014 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/RespectProvidesAnnotationInModuleTest.java",
    "chars": 1818,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/RespectTestScopeWhenUsingAbstractModuleTest.java",
    "chars": 3251,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/SampleParentTestClassWithInnerTestModule.java",
    "chars": 1226,
    "preview": "/*\n * Copyright 2017 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * u"
  },
  {
    "path": "jukito/src/test/java/org/jukito/SingletonTest.java",
    "chars": 5497,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/SomeCoreComponent.java",
    "chars": 967,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/SomeTestClass.java",
    "chars": 824,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/TestTestDescriptions.java",
    "chars": 1377,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/TransitiveDependencyTest.java",
    "chars": 3834,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/UseModulesTest.java",
    "chars": 3061,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/Value3.java",
    "chars": 876,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/environmentdependent/DesktopModule.java",
    "chars": 1117,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/environmentdependent/EnvironmentDependentModulesTest.java",
    "chars": 1992,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/environmentdependent/MobileModule.java",
    "chars": 1115,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito/src/test/java/org/jukito/environmentdependent/TabletModule.java",
    "chars": 1115,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito-samples/pom.xml",
    "chars": 1186,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2"
  },
  {
    "path": "jukito-samples/src/main/java/org/jukito/samples/Car.java",
    "chars": 885,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito-samples/src/main/java/org/jukito/samples/DieselEngine.java",
    "chars": 728,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito-samples/src/main/java/org/jukito/samples/Engine.java",
    "chars": 680,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito-samples/src/main/java/org/jukito/samples/FordMustang.java",
    "chars": 776,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito-samples/src/main/java/org/jukito/samples/PetrolEngine.java",
    "chars": 728,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito-samples/src/main/java/org/jukito/samples/modules/DieselLineModule.java",
    "chars": 909,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito-samples/src/main/java/org/jukito/samples/modules/PetrolLineModule.java",
    "chars": 909,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito-samples/src/test/java/org/jukito/samples/FordMustangTest.java",
    "chars": 1183,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito-samples/src/test/java/org/jukito/samples/FordMustangTest2.java",
    "chars": 1542,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "jukito-samples/src/test/java/org/jukito/samples/FordMustangTest3.java",
    "chars": 1635,
    "preview": "/**\n * Copyright 2013 ArcBees Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * "
  },
  {
    "path": "pom.xml",
    "chars": 14606,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:sc"
  }
]

About this extraction

This page contains the full source code of the ArcBees/Jukito GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 85 files (266.5 KB), approximately 61.3k tokens, and a symbol index with 777 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!