Skip to content

Commit

Permalink
Improved the support for @tested usage in test method parameters, so …
Browse files Browse the repository at this point in the history
…that @tested fields from a base test class get injected into the tested parameter; closes #479.
  • Loading branch information
rliesenfeld committed Nov 19, 2017
1 parent 5c0fd17 commit 3a43e6b
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 12 deletions.
16 changes: 16 additions & 0 deletions main/src/mockit/integration/internal/TestRunnerDecorator.java
Expand Up @@ -168,6 +168,22 @@ protected final void handleMockFieldsForWholeTestClass(@Nonnull Object target)
}
}

protected static void createInstancesForTestedFieldsFromBaseClasses(@Nonnull Object testClassInstance)
{
TestedClassInstantiations testedClasses = TestRun.getTestedClassInstantiations();

if (testedClasses != null) {
TestRun.enterNoMockingZone();

try {
testedClasses.assignNewInstancesToTestedFieldsFromBaseClasses(testClassInstance);
}
finally {
TestRun.exitNoMockingZone();
}
}
}

protected static void createInstancesForTestedFields(@Nonnull Object testClassInstance, boolean beforeSetup)
{
TestedClassInstantiations testedClasses = TestRun.getTestedClassInstantiations();
Expand Down
Expand Up @@ -141,26 +141,27 @@ private void handleMockingOutsideTestMethods(@Nonnull Object target)
}

private static void executeTestMethod(
@Nonnull FakeInvocation invocation, @Nonnull Object target, @Nullable Object... parameters)
@Nonnull FakeInvocation invocation, @Nonnull Object testInstance, @Nullable Object... parameters)
throws Throwable
{
SavePoint savePoint = new SavePoint();

TestRun.setRunningIndividualTest(target);
TestRun.setRunningIndividualTest(testInstance);

FrameworkMethod it = invocation.getInvokedInstance();
Method testMethod = it.getMethod();
Throwable testFailure = null;
boolean testFailureExpected = false;

try {
Object[] annotatedParameters = createInstancesForAnnotatedParameters(target, testMethod, parameters);
createInstancesForTestedFields(target, false);
createInstancesForTestedFieldsFromBaseClasses(testInstance);
Object[] annotatedParameters = createInstancesForAnnotatedParameters(testInstance, testMethod, parameters);
createInstancesForTestedFields(testInstance, false);

invocation.prepareToProceedFromNonRecursiveMock();

Object[] params = annotatedParameters == null ? parameters : annotatedParameters;
it.invokeExplosively(target, params);
it.invokeExplosively(testInstance, params);
}
catch (Throwable thrownByTest) {
testFailure = thrownByTest;
Expand Down
9 changes: 5 additions & 4 deletions main/src/mockit/integration/junit5/JMockitExtension.java
Expand Up @@ -96,19 +96,20 @@ public void beforeTestExecution(@Nonnull ExtensionContext context)
}

@Nonnull Method method = testMethod.get();
@Nonnull Object instance = testInstance.get();
@Nonnull Object actualTestInstance = testInstance.get();
TestRun.enterNoMockingZone();

try {
savePointForTestMethod = new SavePoint();
mockParameters = createInstancesForAnnotatedParameters(instance, method, null);
createInstancesForTestedFields(instance, false);
createInstancesForTestedFieldsFromBaseClasses(actualTestInstance);
mockParameters = createInstancesForAnnotatedParameters(actualTestInstance, method, null);
createInstancesForTestedFields(actualTestInstance, false);
}
finally {
TestRun.exitNoMockingZone();
}

TestRun.setRunningIndividualTest(instance);
TestRun.setRunningIndividualTest(actualTestInstance);
}

@Override
Expand Down
2 changes: 2 additions & 0 deletions main/src/mockit/integration/testng/TestNGRunnerDecorator.java
Expand Up @@ -169,6 +169,8 @@ public void beforeInvocation(@Nonnull IInvokedMethod invokedMethod, @Nonnull ITe
clearTestedObjectsCreatedDuringSetup();
}

createInstancesForTestedFieldsFromBaseClasses(testInstance);

if (!isMethodWithParametersProvidedByTestNG(method)) {
Object[] parameters = testResult.getParameters();
Object[] mockParameters = createInstancesForAnnotatedParameters(testInstance, method, parameters);
Expand Down
7 changes: 7 additions & 0 deletions main/src/mockit/internal/injection/InjectionState.java
Expand Up @@ -57,6 +57,13 @@ boolean setInjectables(@Nonnull List<MockedType> injectables)
return true;
}

void buildListOfInjectableFields(@Nonnull Object testClassInstance, @Nonnull List<MockedType> injectables)
{
currentTestClassInstance = testClassInstance;
setInjectables(injectables);
getServletConfigForInitMethodsIfAny(testClassInstance);
}

void buildListsOfInjectables(@Nonnull Object testClassInstance, @Nonnull List<MockedType> injectables)
{
currentTestClassInstance = testClassInstance;
Expand Down
21 changes: 18 additions & 3 deletions main/src/mockit/internal/injection/TestedClassInstantiations.java
Expand Up @@ -123,11 +123,24 @@ private void addTestedMethodIfApplicable(@Nonnull Method methodFromTestClass)
}
}

public void assignNewInstancesToTestedFieldsFromBaseClasses(@Nonnull Object testClassInstance)
{
injectionState.buildListOfInjectableFields(testClassInstance, injectableFields);

Class<?> testClass = testClassInstance.getClass();

for (TestedField testedField : testedFields) {
if (testedField.isFromBaseClass(testClass)) {
instantiateTestedObject(testClassInstance, testedField);
}
}
}

public void assignNewInstancesToTestedFields(@Nonnull Object testClassInstance, boolean beforeSetup)
{
injectionState.buildListsOfInjectables(testClassInstance, injectableFields);

for (TestedObject testedField : testedFields) {
for (TestedField testedField : testedFields) {
if (!beforeSetup || testedField.isAvailableDuringSetup()) {
instantiateTestedObject(testClassInstance, testedField);
}
Expand Down Expand Up @@ -155,8 +168,10 @@ private void resetTestedFields(boolean duringTearDown)
{
Object testClassInstance = injectionState.getCurrentTestClassInstance();

for (TestedObject testedField : testedFields) {
testedField.clearIfAutomaticCreation(testClassInstance, duringTearDown);
if (testClassInstance != null) {
for (TestedObject testedField : testedFields) {
testedField.clearIfAutomaticCreation(testClassInstance, duringTearDown);
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions main/src/mockit/internal/injection/TestedField.java
Expand Up @@ -23,6 +23,8 @@ final class TestedField extends TestedObject
testedField = field;
}

boolean isFromBaseClass(@Nonnull Class<?> testClass) { return testedField.getDeclaringClass() != testClass; }

@Override
boolean alreadyInstantiated(@Nonnull Object testClassInstance)
{
Expand Down
15 changes: 15 additions & 0 deletions main/test/mockit/TestedClassWithConstructorAndFieldDITest.java
Expand Up @@ -10,6 +10,7 @@
class BaseTest
{
static class Dependency { int doSomething() { return -1; } }
static class Collaborator {}

public static class TestedClass
{
Expand All @@ -25,6 +26,7 @@ public static class TestedClass

@Tested TestedClass tested1;
@Injectable Dependency dependency;
@Tested Collaborator collaborator;

final void verifyTestedObjectFromBaseTestClass(int expectedValueForIntField)
{
Expand Down Expand Up @@ -110,4 +112,17 @@ public void exerciseTestedSubclassObjectUsingConstructorAndFieldInjection(
assertSame(anotherAction, tested2.anotherAction);
assertFalse(tested2.doSomeOperation());
}

static class ClassWithFieldHavingTestedFieldInBaseTestClass { Collaborator collaborator; }

@Tested ClassWithFieldHavingTestedFieldInBaseTestClass tested3;

@Test
public void createTestedParameterInjectingFromTestedFieldInBaseTestClass(
@Tested ClassWithFieldHavingTestedFieldInBaseTestClass tested4)
{
assertNotNull(collaborator);
assertSame(collaborator, tested3.collaborator);
assertSame(collaborator, tested4.collaborator);
}
}

0 comments on commit 3a43e6b

Please sign in to comment.