Skip to content

JUnit 5 and Nested classes #189

Open
@acarpe

Description

@acarpe

Suppose to have this code: a context declared on the enclosing class and one or more nested classes.
It now fails with a no Mockery found in test class

public class NestedJUnit5TestThatDoesNotSatisfyExpectations
{
  @RegisterExtension
  JUnit5Mockery context = new JUnit5Mockery();

  Runnable runnable = context.mock(Runnable.class);

  @Nested
  class NestedClass {
    @Test
    public void doesNotSatisfyExpectations() {
      context.checking(new Expectations() {{
        oneOf (runnable).run();
      }});

      // Return without satisfying the expectation for runnable.run()
    }
  }
}

I tried to make pass this new test

    @Test
    public void testTheJUnit5TestRunnerLooksForTheMockeryInUpperClassOfInnerClasses() {
        listener.runTestIn(NestedJUnit5TestThatDoesNotSatisfyExpectations.class);
        listener.assertTestFailedWith(AssertionError.class);
    }

And as first step I modified the AllDeclaredFields to look in the enclosing classes

public class AllDeclaredFields {
    public static List<Field> in(Class<?> clazz) {
        final ArrayList<Field> fields = new ArrayList<Field>();
        for (Class<?> c = clazz; c != Object.class; c = c.getSuperclass()) {
            fields.addAll(asList(c.getDeclaredFields()));
        }
        for (Class<?> c = clazz.getEnclosingClass(); c != null; c = c.getEnclosingClass()) {
            fields.addAll(asList(c.getDeclaredFields()));
        }
        return fields;
    }
}

but then inside the checkMockery, I don't know how to get the instance of the enclosing types (it has the this$0 field but it's not accessible) to check that the field is not null

if(mockeryField.get(context.getRequiredTestInstance()) == null) {
    throw new IllegalStateException("JUnit5Mockery field should not be null");
}

And I was stuck there.
The only workaround I found was to declare a field inside the nested class and initialize it with the outer field, like this:

package org.jmock.junit5.testdata.jmock.acceptance;

import org.jmock.Expectations;
import org.jmock.auto.Mock;
import org.jmock.junit5.JUnit5Mockery;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

public class NestedJUnit5TestThatDoesNotSatisfyExpectations
{
  @RegisterExtension
  JUnit5Mockery outerContext = new JUnit5Mockery();

  Runnable runnable = context.mock(Runnable.class);

  @Nested
  class NestedClass {
    JUnit5Mockery context = outerContext;

    @Test
    public void doesNotSatisfyExpectations() {
      context.checking(new Expectations() {{
        oneOf (runnable).run();
      }});

      // Return without satisfying the expectation for runnable.run()
    }
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions