Skip to content

Commit

Permalink
Issue-232: Making it possible to reset a single scope
Browse files Browse the repository at this point in the history
  • Loading branch information
dlemures committed Aug 22, 2017
1 parent fb6d400 commit 729136e
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 13 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
//Continue from top

## Release version 1.1.0 (To be released)
* Solves issue #232: Make it possible to reset a single scope. Useful for automation testing when we want to reset the scope used to install test modules.

## Release version 1.0.8 (To be released)
* Solves issue #228: Add scope name to error message: The instance provided by the lazy/provider...
* Solves issue #229: Add parent scope names to error message: No binding was defined for class %s and name %s in scope %s and its parents.
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
GROUP=com.github.stephanenicolas.toothpick
VERSION_NAME=1.0.8-SNAPSHOT
VERSION_NAME=1.1.0-SNAPSHOT

POM_PACKAGING=JAR
POM_DESCRIPTION=DI.
Expand Down
13 changes: 12 additions & 1 deletion toothpick-runtime/src/main/java/toothpick/ScopeImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -522,10 +522,21 @@ private void crashIfClosed() {
}
}

static void reset() {
static void resetUnBoundProviders() {
mapClassesToUnNamedUnBoundProviders.clear();
}

/**
* Resets the state of the scope.
*/
@Override
protected void reset() {
super.reset();
mapClassesToNamedBoundProviders.clear();
mapClassesToUnNamedBoundProviders.clear();
hasTestModules = false;
}

private static class ClassNameComparator implements Comparator<Class> {
@Override
public int compare(Class o1, Class o2) {
Expand Down
15 changes: 12 additions & 3 deletions toothpick-runtime/src/main/java/toothpick/ScopeNode.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package toothpick;

import toothpick.config.Module;

import javax.inject.Provider;
import javax.inject.Singleton;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collection;
Expand All @@ -9,9 +13,6 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.inject.Provider;
import javax.inject.Singleton;
import toothpick.config.Module;

import static java.lang.String.format;

Expand Down Expand Up @@ -200,6 +201,14 @@ public boolean isBoundToScopeAnnotation(Class<? extends Annotation> scopeAnnotat
return scopeAnnotationClasses.contains(scopeAnnotationClass);
}

/**
* Resets the state of the scope.
*/
protected void reset() {
scopeAnnotationClasses.clear();
isOpen = true;
}

@SuppressWarnings({ "unused", "For the sake of completeness of the API." })
Collection<ScopeNode> getChildrenScopes() {
return childrenScopes.values();
Expand Down
17 changes: 14 additions & 3 deletions toothpick-runtime/src/main/java/toothpick/Toothpick.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package toothpick;

import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;
import toothpick.configuration.Configuration;
import toothpick.configuration.ConfigurationHolder;

import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;

/**
* Main class to access toothpick features.
* It allows to create / retrieve scopes and perform injections.
Expand Down Expand Up @@ -126,7 +127,17 @@ public static void reset() {
closeScope(name);
}
ConfigurationHolder.configuration.onScopeForestReset();
ScopeImpl.reset();
ScopeImpl.resetUnBoundProviders();
}

/**
* Reset the state of a single scope. Useful for automation testing when we want to reset the scope used to install
* test modules.
* @param scope we want to reset
*/
public static void reset(Scope scope) {
ScopeNode scopeNode = (ScopeNode) scope;
scopeNode.reset();
}

/**
Expand Down
20 changes: 20 additions & 0 deletions toothpick-runtime/src/test/java/toothpick/ScopeImplTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import org.junit.Test;
import toothpick.config.Module;
import toothpick.data.Bar;
import toothpick.data.BarChild;
import toothpick.data.Foo;
import toothpick.data.IFoo;
import toothpick.registries.NoFactoryFoundException;

import javax.inject.Provider;

Expand Down Expand Up @@ -217,6 +220,23 @@ public void providerGet_shouldFail_whenScopeIsClosed_andThereAreNoDependencies()
//THEN
}

@Test(expected = NoFactoryFoundException.class)
public void reset_shouldResetBoundProviders_andFlagTheTestModuleToFalse() throws Exception {
//GIVEN
ScopeImpl scope = new ScopeImpl("root");
scope.installTestModules(new Module() { {
bind(IFoo.class).to(Foo.class);
bind(Bar.class).withName("name").to(BarChild.class);
} });

//WHEN
scope.reset();

//THEN
scope.installTestModules(); // Should not crash
scope.getInstance(IFoo.class); // Should crash as we don't have the binding for IFoo anymore
}

private static class TestModule extends Module {
public TestModule(Foo foo) {
bind(Foo.class).toInstance(foo);
Expand Down
26 changes: 21 additions & 5 deletions toothpick-runtime/src/test/java/toothpick/ScopeNodeTest.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package toothpick;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.inject.Singleton;
import org.junit.After;
import org.junit.Test;
import toothpick.data.CustomScope;
import toothpick.data.NotAScope;

import javax.inject.Singleton;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
Expand Down Expand Up @@ -423,4 +424,19 @@ public void testGetParentScopeNames_shouldReturnParentNames_whenThereAreNoParent
//THEN
assertThat(parentScopesNames.size(), is(0));
}
}

@Test
public void testReset_shouldClearBoundAnnotations_andFlagTheScopeAsOpen() throws Exception {
//GIVEN
ScopeNode scope = new ScopeImpl("root");
scope.bindScopeAnnotation(CustomScope.class);
scope.close();

//WHEN
scope.reset();

//THEN
assertThat(scope.isBoundToScopeAnnotation(CustomScope.class), is(false));
assertThat(scope.isOpen, is(true));
}
}
18 changes: 18 additions & 0 deletions toothpick-runtime/src/test/java/toothpick/ToothpickTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import org.junit.After;
import org.junit.Test;
import toothpick.configuration.Configuration;
import toothpick.configuration.MultipleRootException;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.notNullValue;
Expand Down Expand Up @@ -218,6 +222,20 @@ public void constructor_shouldThrowException_whenCalled() throws Exception {
//THEN
}

@Test
public void reset_shouldCallResetForProvidedScope() throws Exception {
// GIVEN
ScopeNode mockScope = createMock(ScopeNode.class);
mockScope.reset();
replay(mockScope);

// WHEN
Toothpick.reset(mockScope);

// THEN
verify(mockScope);
}

@After
public void tearDown() throws Exception {
Toothpick.reset();
Expand Down

0 comments on commit 729136e

Please sign in to comment.