Class StaticStateReset

java.lang.Object
io.github.valentinherrmann.levenshtein.StaticStateReset
All Implemented Interfaces:
org.junit.jupiter.api.extension.Extension, org.junit.jupiter.api.extension.InvocationInterceptor, org.junit.jupiter.api.extension.TestInstantiationAwareExtension

public class StaticStateReset extends Object implements org.junit.jupiter.api.extension.InvocationInterceptor
Resets attributes that the student declared static although the test expects an instance attribute (issue #35), so that their state does not leak from one test into the next.

Such an attribute is a deviation (the structural test fails), but behaviour tests go on with it. Its value is shared by all objects and, because the class is never reloaded, by all tests, so results could depend on the order of the tests. Before each test this extension writes the value back that the attribute had right after the class was initialised.

  • Only attributes that a live attribute wrapper reports with an unexpected static are reset. An attribute that any live wrapper expects to be static is never reset, even if another wrapper (e.g. of an earlier test class) reported it.
  • Arrays (also nested ones) are copied deeply, so a test gets a fresh array with the initial content. Other objects (e.g. lists) are restored by reference: their content stays as an earlier test left it.
  • static final attributes cannot be reset.
  • Within one test the state stays shared on purpose: that is the wrong behaviour the student should see.

The extension is part of LevenshteinTest and HiddenLevenshteinTest. Once per test, before the first @BeforeEach method or else before the test method, it first checks all attribute wrappers created so far (their lookup runs once anyway), so the initial value is recorded before the first test can change it, and then resets. Consequences:

  • Wrappers are looked up before the test runs, so LevenshteinSettings must be configured in a static initializer or @BeforeAll; a change inside a test method or @BeforeEach comes too late for the attribute wrappers that exist already.
  • The initial value is the value when the first wrapper reported the attribute. If student code changed the attribute before (e.g. a test class without a wrapper for it ran first), that changed value is restored; the real initial value cannot be recovered without reloading the class.

Supervision: Ares arms its security policy in its own invocation interceptor (JupiterSecurityExtension.interceptBeforeEachMethod/interceptTestMethod). The composed annotations declare @Public/@Hidden before @ExtendWith(StaticStateReset.class), so JUnit registers Ares first and its interceptor wraps this one: the lookups and class initialisations triggered here run supervised, like every other lookup. Keep that order.

  • Nested Class Summary

    Nested classes/interfaces inherited from interface org.junit.jupiter.api.extension.InvocationInterceptor

    org.junit.jupiter.api.extension.InvocationInterceptor.Invocation<T>

    Nested classes/interfaces inherited from interface org.junit.jupiter.api.extension.TestInstantiationAwareExtension

    org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope
  • Constructor Summary

    Constructors
    Constructor
    Description
     
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    interceptBeforeEachMethod(org.junit.jupiter.api.extension.InvocationInterceptor.Invocation<Void> invocation, org.junit.jupiter.api.extension.ReflectiveInvocationContext<Method> invocationContext, org.junit.jupiter.api.extension.ExtensionContext extensionContext)
     
    void
    interceptTestMethod(org.junit.jupiter.api.extension.InvocationInterceptor.Invocation<Void> invocation, org.junit.jupiter.api.extension.ReflectiveInvocationContext<Method> invocationContext, org.junit.jupiter.api.extension.ExtensionContext extensionContext)
     
    void
    interceptTestTemplateMethod(org.junit.jupiter.api.extension.InvocationInterceptor.Invocation<Void> invocation, org.junit.jupiter.api.extension.ReflectiveInvocationContext<Method> invocationContext, org.junit.jupiter.api.extension.ExtensionContext extensionContext)
     

    Methods inherited from class Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

    Methods inherited from interface org.junit.jupiter.api.extension.InvocationInterceptor

    interceptAfterAllMethod, interceptAfterEachMethod, interceptBeforeAllMethod, interceptDynamicTest, interceptTestClassConstructor, interceptTestFactoryMethod

    Methods inherited from interface org.junit.jupiter.api.extension.TestInstantiationAwareExtension

    getTestInstantiationExtensionContextScope
  • Constructor Details

    • StaticStateReset

      public StaticStateReset()
  • Method Details

    • interceptBeforeEachMethod

      public void interceptBeforeEachMethod(org.junit.jupiter.api.extension.InvocationInterceptor.Invocation<Void> invocation, org.junit.jupiter.api.extension.ReflectiveInvocationContext<Method> invocationContext, org.junit.jupiter.api.extension.ExtensionContext extensionContext) throws Throwable
      Specified by:
      interceptBeforeEachMethod in interface org.junit.jupiter.api.extension.InvocationInterceptor
      Throws:
      Throwable
    • interceptTestMethod

      public void interceptTestMethod(org.junit.jupiter.api.extension.InvocationInterceptor.Invocation<Void> invocation, org.junit.jupiter.api.extension.ReflectiveInvocationContext<Method> invocationContext, org.junit.jupiter.api.extension.ExtensionContext extensionContext) throws Throwable
      Specified by:
      interceptTestMethod in interface org.junit.jupiter.api.extension.InvocationInterceptor
      Throws:
      Throwable
    • interceptTestTemplateMethod

      public void interceptTestTemplateMethod(org.junit.jupiter.api.extension.InvocationInterceptor.Invocation<Void> invocation, org.junit.jupiter.api.extension.ReflectiveInvocationContext<Method> invocationContext, org.junit.jupiter.api.extension.ExtensionContext extensionContext) throws Throwable
      Specified by:
      interceptTestTemplateMethod in interface org.junit.jupiter.api.extension.InvocationInterceptor
      Throws:
      Throwable