A powerful CLI tool that analyzes Java legacy code, generates Mockito test mocks, and maps API invocation sequences across your entire codebase.
- π Code Analysis: Deep analysis of Java classes including complexity, dependencies, and testability
- π§ͺ Mock Generation: Automatically generates Mockito test classes with proper annotations
- π API Sequence Mapping: Traces method call sequences up to 4 levels deep across files
- π² Visual Tree Display: Shows method invocation hierarchy in ASCII tree format
- π Organized Output: Auto-creates separate directories for generated tests and API reports
- π Risk Detection: Identifies high-risk areas that need thorough testing
- π‘ Smart Suggestions: Provides specific test coverage recommendations
- π¨ Cross-Platform: Works on Windows, Linux, and macOS with ASCII-safe output
- Installation
- Quick Start
- Commands Reference
- Understanding API Analysis
- Interpreting Results
- Output Directory Structure
- Use Cases & Examples
- Best Practices
Requirements:
- Python 3.7 or higher
- No external dependencies required (pure Python!)
Setup:
# Clone or download the repository
cd legacy-analyzer
# Make the CLI executable (Unix/Linux/macOS)
chmod +x legacy-cli
# Ready to use!
./legacy-cli --help
# On Windows, use:
legacy-cli.bat --help
# Or use Python directly on any platform:
python main.py --helpAdding to PATH (Optional):
# Unix/Linux/macOS - Add to ~/.bashrc or ~/.zshrc
export PATH="$PATH:/path/to/legacy-analyzer"
# Windows - Add the directory to your System PATH environment variable
# Then you can use: legacy-cli analyze MyFile.java# Using legacy-cli (recommended)
./legacy-cli analyze examples/UserService.java
# Or with Python directly
python main.py analyze examples/UserService.javaWhat you'll see:
- Complexity breakdown (Simple/Moderate/Complex methods)
- Mockable dependencies
- Testability score (0-100)
- Test coverage suggestions
- Risk areas
# Using legacy-cli (recommended)
./legacy-cli generate examples/UserService.java --output UserServiceTest.java
# Or with Python directly
python main.py generate examples/UserService.java --output UserServiceTest.javaOutput: generated-tests/UserServiceTest.java (auto-created directory)
Contains:
- @Mock annotations for dependencies
- @InjectMocks for class under test
- Test method stubs for all public methods
- Exception test cases
# Using legacy-cli (recommended)
./legacy-cli api-analyze examples
# Or with Python directly
python main.py api-analyze examplesWhat you'll see:
- All public APIs (methods) discovered
- Tree view of method invocation sequences
- Cross-file method call tracking
- External API dependencies highlighted
- Exception handling paths
Analyzes a Java class for testability and complexity.
# Using legacy-cli
./legacy-cli analyze <java-file> [--verbose]
# Or with Python
python main.py analyze <java-file> [--verbose]Options:
--verbose, -v- Show detailed analysis
Example:
./legacy-cli analyze examples/UserService.java --verboseOutput Sections:
- Complexity Analysis: Method count breakdown
- Dependencies: Mockable fields
- Testability Score: 0-100 rating
- Test Coverage Suggestions: What to test
- Risk Areas: High-priority test targets
- Public Methods: List of testable methods
Creates a complete JUnit + Mockito test class.
# Using legacy-cli
./legacy-cli generate <java-file> [options]
# Or with Python
python main.py generate <java-file> [options]Options:
--output, -o FILE- Output file name (saved togenerated-tests/)--quick-mocks- Generate only mock field declarations--no-setup- Skip @Before setup method
Examples:
# Full test class
./legacy-cli generate examples/UserService.java --output UserServiceTest.java
# Output: generated-tests/UserServiceTest.java
# Quick mocks only (for copy-paste)
./legacy-cli generate examples/UserService.java --quick-mocks
# Save to custom location (absolute path)
./legacy-cli generate examples/UserService.java --output /tmp/MyTest.javaGenerated Test Structure:
@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {
@Mock
private UserDAO userDAO;
@InjectMocks
private UserService userService;
@Before
public void setUp() { }
@Test
public void testGetUserById_Success() { }
@Test(expected = Exception.class)
public void testGetUserById_ThrowsException() { }
}Scans entire project to map all public APIs and their invocation sequences.
# Using legacy-cli
./legacy-cli api-analyze <project-directory> [options]
# Or with Python
python main.py api-analyze <project-directory> [options]Options:
--export, -e FILE- Export to markdown (saved toapi-reports/)--summary- Show only summary table
Examples:
# Full analysis with tree view
./legacy-cli api-analyze examples
# Export to markdown report
./legacy-cli api-analyze examples --export api-report.md
# Output: api-reports/api-report.md
# Show summary table only
./legacy-cli api-analyze examples --summaryThe api-analyze command discovers:
- Public APIs: All
publicmethods (excluding constructors) - Call Sequences: Method invocation chains up to 4 levels deep
- Cross-File Calls: Methods calling other methods in different files
- External Dependencies: Calls to libraries, frameworks, databases
- Exception Paths: Thrown and caught exceptions
API Method (depth 0)
βββ Internal Method Call (depth 1)
β βββ External DB Call (depth 2)
β βββ External Logger Call (depth 2)
βββ External API Call (depth 1)
Depth Limits:
- Maximum depth: 4 levels
- Prevents infinite recursion
- Stops at external dependencies
|-- Non-last item in list (has siblings below)
+-- Last item in list (no more siblings)
| Continuation line (parent has more children)
Spacing (parent is complete)
Example Output:
Call Sequence (Tree View):
|-- newEmail.contains("@")
|-- user.setEmail(newEmail)
|-- UserDAO.update(user)
+-- [UserService.java] UserService.getUserById(userId)
|-- [EXTERNAL] Logger.info("Getting user...") (depth: 1)
|-- [EXTERNAL] UserDAO.findById(userId) (depth: 1)
+-- [EXTERNAL] Logger.warn("User not found") (depth: 1)
Interpretation:
updateUserEmailcalls 4 methods sequentially- The last call (
getUserById) is an internal method getUserByIdmakes 3 external calls (to Logger and UserDAO)- External calls are highlighted with
[EXTERNAL] - Depth indicators show nesting level
[EXTERNAL]- Third-party library, framework, or JDK call[FileName.java]- Internal project method with source file nameClassName.methodName(params)- Full method signature
The same sequence in numbered format:
Call Sequence (Ordered List):
1. newEmail.contains("@")
2. user.setEmail(newEmail)
3. UserDAO.update(user)
4. [UserService.java] UserService.getUserById(userId)
5. [EXTERNAL] Logger.info("Getting user...") (depth: 1)
6. [EXTERNAL] UserDAO.findById(userId) (depth: 1)
7. [EXTERNAL] Logger.warn("User not found") (depth: 1)
Use the ordered list to:
- Understand execution order
- Count total method calls
- Identify performance bottlenecks
External API Calls:
[EXT] Logger.info("Getting user...")
[EXT] UserDAO.findById(userId)
[EXT] NotificationService.send(...)
These are potential integration points that need:
- Mocking in tests
- Error handling
- Performance monitoring
- Circuit breakers (if remote services)
Exception Paths:
! Throws: IllegalArgumentException
! Throws: Exception
! Catches: SQLException
Interpretation:
Throws:- Declared in method signature (throws Exception)Throws:(in body) - Explicitthrow new Exception()statementsCatches:- Try-catch blocks handling exceptions
Testing implications:
- Test happy path AND exception paths
- Verify exception messages
- Test error recovery logic
legacy-analyzer/
βββ legacy-cli # Unix/Linux/macOS executable
βββ legacy-cli.bat # Windows batch file
βββ main.py # CLI entry point
βββ java_parser.py # Java parser
βββ analyzer.py # Code analyzer
βββ mock_generator.py # Test generator
βββ api_analyzer.py # API sequence analyzer
βββ output_formatter.py # Console formatter
βββ api_output_formatter.py # API formatter
βββ .gitignore # Git ignore
βββ examples/
β βββ UserService.java
β βββ PaymentProcessor.java
βββ generated-tests/ # β AUTO-CREATED
β βββ UserServiceTest.java
βββ api-reports/ # β AUTO-CREATED
βββ api-analysis.md
Generated Directories:
generated-tests/- All test files (git-ignored)api-reports/- All markdown reports (git-ignored)
Path Behavior:
- Relative paths: Saved to auto-created subdirectories
- Absolute paths: Saved to exact location specified
# Relative β generated-tests/MyTest.java
./legacy-cli generate File.java --output MyTest.java
# Absolute β /home/user/custom/MyTest.java
./legacy-cli generate File.java --output /home/user/custom/MyTest.javaScenario: You have a 500-line OrderService.java with no tests.
# Step 1: Analyze complexity
./legacy-cli analyze OrderService.java --verbose
# Step 2: Generate test scaffolding
./legacy-cli generate OrderService.java --output OrderServiceTest.java
# Step 3: Customize generated tests
# Edit generated-tests/OrderServiceTest.java
# Add specific assertions and mock behaviorsWhat you get:
- Understanding of code complexity
- Complete test class structure
- Mock setup for all dependencies
- Test stubs for all public methods
Scenario: You need to understand how processPayment works across multiple classes.
# Analyze the entire payment module
./legacy-cli api-analyze src/payment/ --export payment-api-flow.mdWhat you learn:
- Which methods
processPaymentcalls - Cross-class dependencies
- External service integrations (PaymentGateway, Database)
- Exception handling strategy
Example result:
processPayment()
βββ validateCard() [CardValidator.java]
β βββ [EXTERNAL] CardDatabase.lookup()
β βββ [EXTERNAL] FraudService.check()
βββ [EXTERNAL] PaymentGateway.charge()
βββ sendConfirmation() [NotificationService.java]
βββ [EXTERNAL] EmailService.send()
βββ [EXTERNAL] SMSService.send()
Scenario: You want to refactor a complex method but need to understand its impact.
# Before refactoring
./legacy-cli api-analyze src/ --export before-refactor.md
# After refactoring
./legacy-cli api-analyze src/ --export after-refactor.md
# Compare the two markdown files to see changesBenefits:
- Document original behavior
- Verify refactoring didn't change call sequences
- Identify unintended side effects
Scenario: Reviewing a PR that adds new APIs.
# Generate API documentation
./legacy-cli api-analyze src/ --export pr-123-api-changes.mdUse the report to:
- Review method invocation patterns
- Identify missing error handling
- Spot potential performance issues
- Document API contracts
- Always review generated tests - They're starting points, not complete tests
- Add specific assertions - Replace generic
assertNotNullwith business logic checks - Mock external dependencies - Database, HTTP clients, file I/O
- Test edge cases - Null inputs, empty lists, boundary values
- Verify interactions - Use
verify()to check method calls
Example customization:
// Generated (generic)
@Test
public void testGetUserById_Success() {
when(userDAO.findById(1)).thenReturn(mock(User.class));
User result = userService.getUserById(1);
assertNotNull(result);
}
// Customized (specific)
@Test
public void testGetUserById_Success() {
User mockUser = new User(1, "John", "john@example.com");
when(userDAO.findById(1)).thenReturn(mockUser);
User result = userService.getUserById(1);
assertEquals(1, result.getId());
assertEquals("John", result.getName());
verify(userDAO, times(1)).findById(1);
}- Start with small modules - Analyze one package at a time
- Focus on complex methods - Methods with 20+ lines and deep nesting
- Document external dependencies - Note which need mocking/stubbing
- Track exception flows - Ensure all paths are tested
- Export to markdown - Keep reports in version control for historical reference
# Analyze by package
./legacy-cli api-analyze src/payment --export payment-apis.md
./legacy-cli api-analyze src/orders --export order-apis.md
./legacy-cli api-analyze src/users --export user-apis.md
# Use --summary for quick overview
./legacy-cli api-analyze src/ --summary[S]Simple (β€5 lines) - Easy to test[M]Moderate (6-15 lines) - Needs good coverage[C]Complex (>15 lines) - High priority for testing
- 80-100 (Good) - Easy to test, well-structured
- 60-79 (Fair) - Some improvements needed
- 0-59 (Needs Improvement) - Difficult to test, refactoring recommended
Factors affecting score:
- Constructor injection (+20 points)
- Few dependencies (+10 points)
- No static methods (+5 points)
- Clear method signatures (+5 points)
- Check that Java files have
publicmethods - Ensure you're pointing to the correct directory
- Verify files have
.javaextension
- Ensure Java syntax is valid
- Check for unusual annotations or syntax
- File must contain a valid class declaration
- Tool uses ASCII-safe characters
- Should work on all platforms
- If issues persist, redirect output:
./legacy-cli api-analyze examples > output.txt
legacy-analyzer/
βββ π README.md β You are here
βββ π CHANGELOG.md β Version history
βββ π QUICKSTART.md β 2-minute guide
βββ legacy-cli β Unix/Linux/macOS executable
βββ legacy-cli.bat β Windows executable
βββ examples/ β Sample Java files
- UserService.java - CRUD service with DAO pattern
- PaymentProcessor.java - Complex business logic with external calls
Try them:
./legacy-cli analyze examples/UserService.java
./legacy-cli api-analyze examplesFound a bug? Have a feature request?
- Check existing issues
- Create a new issue with details
- Include example Java files if applicable
This tool is provided as-is for analyzing and testing Java code.
analyze- Understand single file complexitygenerate- Create test scaffolding quicklyapi-analyze- Map entire project API flows- Tree View - Visualize method call hierarchy
- External Calls - Identify integration points
- Auto-organized - Files saved to clean directories
Start simple, analyze often, test thoroughly.
Built with β€οΈ for testing legacy Java code