Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Resolve type variables in generic test class hierarchies#320

Open
amondnet wants to merge 4 commits into
AutoParams:mainAutoParams/AutoParams:mainfrom
amondnet:fix/issue-277-generic-test-class-type-resolutionamondnet/AutoParams:fix/issue-277-generic-test-class-type-resolutionCopy head branch name to clipboard
Open

Resolve type variables in generic test class hierarchies#320
amondnet wants to merge 4 commits into
AutoParams:mainAutoParams/AutoParams:mainfrom
amondnet:fix/issue-277-generic-test-class-type-resolutionamondnet/AutoParams:fix/issue-277-generic-test-class-type-resolutionCopy head branch name to clipboard

Conversation

@amondnet

Copy link
Copy Markdown
Contributor

Summary

Fixes #277 by implementing type variable resolution for generic test class hierarchies. When test methods are inherited from abstract generic test classes, AutoParams can now correctly resolve type parameters to their concrete types.

Problem

Previously, when a test class like CategoryTest extends HierarchyEntityTest<Category> inherited test methods with generic parameters T, AutoParams failed with:

RuntimeException: Object cannot be created with the given query

This occurred because parameter.getParameterizedType() returned TypeVariable instead of the concrete type Category.

Solution

Enhanced TestResolutionContext to:

  • Detect TypeVariable parameters in test methods
  • Walk the test class hierarchy to find type variable mappings
  • Resolve type variables using the test class's generic superclass information
  • Support multi-level inheritance and generic interfaces
  • Handle recursive type variable resolution with defensive type checking

Changes

Modified: TestResolutionContext.java

  • Added resolveTypeVariable() - Main entry point for type resolution
  • Added resolveTypeVariableFromClass() - Walks class hierarchy recursively
  • Added resolveTypeVariableFromType() - Resolves from parameterized types with safe casting

Added: SpecsForGenericTestClass.java

  • Tests single-level inheritance (CategoryTest extends HierarchyEntityTest<Category>)
  • Tests multi-level inheritance (ProductTest extends MiddleEntityTest<Product> extends HierarchyEntityTest)
  • Tests generic interface resolution (CategoryRepositoryTest with multiple type parameters)

Test Coverage

All new tests pass, covering:

  • ✅ Single-level generic inheritance
  • ✅ Multi-level generic inheritance (3+ levels)
  • ✅ Generic interfaces with type parameters
  • ✅ Nested type variable chains
  • ✅ Fallback to type bounds when resolution fails

Build Status

BUILD SUCCESSFUL
All tests passing
Checkstyle compliant

Example Usage

abstract class HierarchyEntityTest<T extends HierarchyEntity<T>> {
    @ParameterizedTest
    @AutoSource
    void changeParent(T sut, T parent) {
        sut.changeParent(parent);
        // Assertions...
    }
}

class CategoryTest extends HierarchyEntityTest<Category> {
    // Tests now work! AutoParams resolves T -> Category
}

Impact

  • No breaking changes
  • Backward compatible with existing test patterns
  • Enables generic test base classes (common pattern in domain-driven design)
  • Handles complex inheritance hierarchies robustly

Review Notes

This PR addresses:

  1. The original issue 추상 제네릭 테스트클래스 의 테스트 구현체에서 <T> 타입 식별 불가능 #277 (single-level inheritance)
  2. Code review findings (multi-level inheritance, defensive casting)
  3. Edge cases (generic interfaces, recursive resolution)

Ready for review and testing.

When test methods are inherited from abstract generic test classes,
parameter types appear as TypeVariable at runtime instead of their
concrete types. This caused AutoParams to fail with "Object cannot
be created" errors.

This change enhances TestResolutionContext to detect TypeVariable
parameters and resolve them using the test class's generic superclass
information, mapping type variables to their actual type arguments.

Fixes AutoParams#277
Improve type variable resolution to handle complex inheritance
hierarchies and generic interfaces. The original implementation
only checked the immediate superclass, which failed for:
- Multi-level generic inheritance
- Generic interfaces
- Nested type variable chains

Changes:
- Add defensive type checking before ClassCastException-prone casts
- Walk entire class hierarchy to find type variable mappings
- Check generic interfaces at each level
- Handle recursive type variable resolution
- Add comprehensive test coverage for edge cases

This enhancement addresses code review findings while maintaining
backward compatibility with the existing single-level inheritance
use case.
Address critical silent failure issues identified in code review:

1. Add explicit warning when type variable resolution falls back
   to bounds or Object.class, providing users with actionable
   guidance on how to fix their test class hierarchy

2. Add test for unresolvable type variables (ConcreteUnboundTest)
   to verify fallback behavior works correctly

3. Add test for nested type variable chains (ThreeLevelTest with
   BaseLevel<A> -> MiddleLevel<B> -> HigherLevel<C> -> Category)
   to ensure recursive resolution handles multi-level mappings

These changes ensure users receive clear feedback when type
resolution fails instead of silently getting wrong types, making
debugging configuration issues straightforward.

Addresses PR review findings: silent-failure-hunter issues #1, AutoParams#2, AutoParams#3
and pr-test-analyzer critical gaps #1, AutoParams#2.
@amondnet

amondnet commented Oct 19, 2025

Copy link
Copy Markdown
Contributor Author

Remaining

  • Multiple null returns without context (HIGH)
  • Type checking guards hide problems (HIGH)
  • No safeguard against infinite recursion (MEDIUM)
  • Additional test coverage improvements

Enhance type variable resolution with comprehensive diagnostic logging
and protection against infinite recursion, improving debuggability and
robustness.

Add recursion depth tracking with configurable maximum depth (50 levels)
to prevent stack overflow from circular type variable references. When
exceeded, throw IllegalStateException with clear error message.

Add diagnostic logging controlled by system property
'autoparams.debug.typeResolution'. When enabled, log:
- Type resolution initiation and completion
- Class hierarchy traversal at each depth level
- Type matching success with mapping details
- Types skipped due to type guards (non-parameterized, non-class)

This helps developers understand and debug complex generic type
hierarchies without needing to step through with a debugger.
@amondnet
amondnet marked this pull request as ready for review October 19, 2025 11:01
Copilot AI review requested due to automatic review settings October 19, 2025 11:01

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes issue #277 by implementing type variable resolution for generic test class hierarchies, enabling AutoParams to correctly resolve type parameters when test methods are inherited from abstract generic test classes.

Key Changes:

  • Enhanced TestResolutionContext to resolve TypeVariable parameters by traversing the test class hierarchy and mapping type variables to their concrete types
  • Added comprehensive test coverage in SpecsForGenericTestClass.java for single-level, multi-level inheritance, and generic interface scenarios
  • Implemented depth limits and debug logging for type resolution with fallback to type bounds when resolution fails

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
TestResolutionContext.java Added type variable resolution logic with hierarchy traversal, recursive resolution, and safeguards against infinite recursion
SpecsForGenericTestClass.java New test file covering single/multi-level inheritance, generic interfaces, and edge cases for type variable resolution

TypeFormatter.format(fallbackType, false)
);

System.err.println("WARNING: " + message);

Copilot AI Oct 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using a proper logging framework (e.g., SLF4J, java.util.logging) instead of System.err.println for warning messages. This would provide better control over log levels, formatting, and output destinations in production environments.

Copilot uses AI. Check for mistakes.
}

private void debugLog(String format, Object... args) {
System.err.println("DEBUG [TypeResolution]: " + String.format(format, args));

Copilot AI Oct 19, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using a proper logging framework instead of System.err.println for debug logging. This would integrate better with existing logging infrastructure and allow proper configuration of debug levels.

Copilot uses AI. Check for mistakes.
@amondnet amondnet changed the title Fix #277: Resolve type variables in generic test class hierarchies Resolve type variables in generic test class hierarchies Oct 19, 2025
@gyuwon

gyuwon commented Nov 20, 2025

Copy link
Copy Markdown
Contributor

@amondnet 우선 좋은 코드 작성해 주셔서 감사드립니다!
그런데 저는 #277 이 해결되어야 할 주제인지 고민이 됩니다. 테스트 코드가 운영코드를 상속받는 설계는 테스트 코드와 운영 코드의 결합을 높이기 때문에 이런 테스트 작성 방식은 피해야 할 패턴이라고 생각되고 AutoParams가 안티 패턴을 지원하는 것이 바람직한 것인지 의문이네요. 어떻게 생각하시나요?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

추상 제네릭 테스트클래스 의 테스트 구현체에서 <T> 타입 식별 불가능

3 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.