Sure, here is a test case generator for the given problem statement "Spring Tile":

```python
import random

def generate_maze(W, H):
    # Initialize the maze with walls
    maze = [['#' for _ in range(W)] for _ in range(H)]
    
    # Define the inner area where we can place other tiles
    for i in range(1, H-1):
        for j in range(1, W-1):
            maze[i][j] = random.choice(['.', '*', '#'])
    
    # Make sure there is exactly one 's' and one 'g'
    # Avoid placing 's' or 'g' in walls or springs
    while True:
        s_x, s_y = random.randint(1, H-2), random.randint(1, W-2)
        g_x, g_y = random.randint(1, H-2), random.randint(1, W-2)
        if maze[s_x][s_y] != '#' and maze[s_x][s_y] != '*' and maze[g_x][g_y] != '#' and maze[g_x][g_y] != '*' and (s_x != g_x or s_y != g_y):
            maze[s_x][s_y] = 's'
            maze[g_x][g_y] = 'g'
            break

    # Convert the maze to the required format (list of strings)
    maze = [''.join(row) for row in maze]
    
    return maze

def tcgen():
    W = random.randint(3, 500)
    H = random.randint(3, 500)

    maze = generate_maze(W, H)
    
    # Print the maze in the required format
    print(W, H)
    for row in maze:
        print(row)

# Example usage:
if __name__ == "__main__":
    tcgen()
```

### Explanation:
1. **Maze Initialization**:
    - The maze is initialized with walls (`#`) on its outer layer.
    - Inner cells are filled with random tiles (`'.'`, `'*'`, `'#'`).

2. **Placing 's' (start) and 'g' (goal)**:
    - Random positions are chosen for `s` and `g` ensuring they are not placed on a wall or a spring.
    - It also ensures `s` and `g` do not overlap.

3. **Output**:
    - The maze is printed in the required format where the first line contains the dimensions `W` and `H`.
    - Subsequent lines represent the maze row by row.

The generated maze will respect the constraints and format specified in the problem statement. You can run the `tcgen()` function to generate a random test case each time.