-
Notifications
You must be signed in to change notification settings - Fork 18
refactor: consolidate player data into single source of truth (#210) #352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,201 +1,67 @@ | ||
| using Dotnet.Samples.AspNetCore.WebApi.Enums; | ||
| using Dotnet.Samples.AspNetCore.WebApi.Models; | ||
| using Dotnet.Samples.AspNetCore.WebApi.Utilities; | ||
|
|
||
| namespace Dotnet.Samples.AspNetCore.WebApi.Tests.Utilities; | ||
|
|
||
| /// <summary> | ||
| /// A Fake is a working implementation that’s simpler than the real one. | ||
| /// It usually has some “real” logic but is not suitable for production | ||
| /// Test data factory for Player entities. | ||
| /// Wraps production data from PlayerData with test-specific modifications (e.g., GUID assignment). | ||
| /// A Fake is a working implementation that's simpler than the real one. | ||
| /// It usually has some "real" logic but is not suitable for production | ||
| /// (e.g., an in‑memory database instead of a full SQL Server). Fakes are | ||
| /// useful when you need behavior that’s closer to reality but still want | ||
| /// useful when you need behavior that's closer to reality but still want | ||
| /// to avoid external dependencies. | ||
| /// </summary> | ||
| public static class PlayerFakes | ||
| { | ||
| /// <summary> | ||
| /// Returns the starting 11 players with generated GUIDs for in-memory testing. | ||
| /// Reuses production player data from PlayerData.MakeStarting11(). | ||
| /// </summary> | ||
| public static List<Player> MakeStarting11() | ||
| { | ||
| return | ||
| [ | ||
| new() | ||
| { | ||
| Id = Guid.NewGuid(), | ||
| FirstName = "Damián", | ||
| MiddleName = "Emiliano", | ||
| LastName = "Martínez", | ||
| DateOfBirth = new DateTime(1992, 9, 1, 0, 0, 0, DateTimeKind.Utc), | ||
| SquadNumber = 23, | ||
| Position = Position.Goalkeeper.Text, | ||
| AbbrPosition = Position.Goalkeeper.Abbr, | ||
| Team = "Aston Villa FC", | ||
| League = "Premier League", | ||
| Starting11 = true, | ||
| }, | ||
| new() | ||
| { | ||
| Id = Guid.NewGuid(), | ||
| FirstName = "Nahuel", | ||
| LastName = "Molina", | ||
| DateOfBirth = new DateTime(1998, 4, 5, 0, 0, 0, DateTimeKind.Utc), | ||
| SquadNumber = 26, | ||
| Position = Position.RightBack.Text, | ||
| AbbrPosition = Position.RightBack.Abbr, | ||
| Team = "Altético Madrid", | ||
| League = "La Liga", | ||
| Starting11 = true, | ||
| }, | ||
| new() | ||
| { | ||
| Id = Guid.NewGuid(), | ||
| FirstName = "Cristian", | ||
| MiddleName = "Gabriel", | ||
| LastName = "Romero", | ||
| DateOfBirth = new DateTime(1998, 4, 26, 0, 0, 0, DateTimeKind.Utc), | ||
| SquadNumber = 13, | ||
| Position = Position.CentreBack.Text, | ||
| AbbrPosition = Position.CentreBack.Abbr, | ||
| Team = "Tottenham Hotspur", | ||
| League = "Premier League", | ||
| Starting11 = true, | ||
| }, | ||
| new() | ||
| { | ||
| Id = Guid.NewGuid(), | ||
| FirstName = "Nicolás", | ||
| MiddleName = "Hernán Gonzalo", | ||
| LastName = "Otamendi", | ||
| DateOfBirth = new DateTime(1988, 2, 11, 0, 0, 0, DateTimeKind.Utc), | ||
| SquadNumber = 19, | ||
| Position = Position.CentreBack.Text, | ||
| AbbrPosition = Position.CentreBack.Abbr, | ||
| Team = "SL Benfica", | ||
| League = "Liga Portugal", | ||
| Starting11 = true, | ||
| }, | ||
| new() | ||
| { | ||
| Id = Guid.NewGuid(), | ||
| FirstName = "Nicolás", | ||
| MiddleName = "Alejandro", | ||
| LastName = "Tagliafico", | ||
| DateOfBirth = new DateTime(1992, 8, 30, 0, 0, 0, DateTimeKind.Utc), | ||
| SquadNumber = 3, | ||
| Position = Position.LeftBack.Text, | ||
| AbbrPosition = Position.LeftBack.Abbr, | ||
| Team = "Olympique Lyon", | ||
| League = "Ligue 1", | ||
| Starting11 = true, | ||
| }, | ||
| new() | ||
| { | ||
| Id = Guid.NewGuid(), | ||
| FirstName = "Ángel", | ||
| MiddleName = "Fabián", | ||
| LastName = "Di María", | ||
| DateOfBirth = new DateTime(1988, 2, 13, 0, 0, 0, DateTimeKind.Utc), | ||
| SquadNumber = 11, | ||
| Position = Position.RightWinger.Text, | ||
| AbbrPosition = Position.RightWinger.Abbr, | ||
| Team = "SL Benfica", | ||
| League = "Liga Portugal", | ||
| Starting11 = true, | ||
| }, | ||
| new() | ||
| { | ||
| Id = Guid.NewGuid(), | ||
| FirstName = "Rodrigo", | ||
| MiddleName = "Javier", | ||
| LastName = "de Paul", | ||
| DateOfBirth = new DateTime(1994, 5, 23, 0, 0, 0, DateTimeKind.Utc), | ||
| SquadNumber = 7, | ||
| Position = Position.CentralMidfield.Text, | ||
| AbbrPosition = Position.CentralMidfield.Abbr, | ||
| Team = "Altético Madrid", | ||
| League = "La Liga", | ||
| Starting11 = true, | ||
| }, | ||
| new() | ||
| { | ||
| Id = Guid.NewGuid(), | ||
| FirstName = "Enzo", | ||
| MiddleName = "Jeremías", | ||
| LastName = "Fernández", | ||
| DateOfBirth = new DateTime(2001, 1, 16, 0, 0, 0, DateTimeKind.Utc), | ||
| SquadNumber = 24, | ||
| Position = Position.CentralMidfield.Text, | ||
| AbbrPosition = Position.CentralMidfield.Abbr, | ||
| Team = "Chelsea FC", | ||
| League = "Premier League", | ||
| Starting11 = true, | ||
| }, | ||
| new() | ||
| { | ||
| Id = Guid.NewGuid(), | ||
| FirstName = "Alexis", | ||
| LastName = "Mac Allister", | ||
| DateOfBirth = new DateTime(1998, 12, 23, 0, 0, 0, DateTimeKind.Utc), | ||
| SquadNumber = 20, | ||
| Position = Position.CentralMidfield.Text, | ||
| AbbrPosition = Position.CentralMidfield.Abbr, | ||
| Team = "Liverpool FC", | ||
| League = "Premier League", | ||
| Starting11 = true, | ||
| }, | ||
| new() | ||
| { | ||
| Id = Guid.NewGuid(), | ||
| FirstName = "Lionel", | ||
| MiddleName = "Andrés", | ||
| LastName = "Messi", | ||
| DateOfBirth = new DateTime(1987, 6, 23, 0, 0, 0, DateTimeKind.Utc), | ||
| SquadNumber = 10, | ||
| Position = Position.RightWinger.Text, | ||
| AbbrPosition = Position.RightWinger.Abbr, | ||
| Team = "Inter Miami CF", | ||
| League = "Major League Soccer", | ||
| Starting11 = true, | ||
| }, | ||
| new() | ||
| { | ||
| Id = Guid.NewGuid(), | ||
| FirstName = "Julián", | ||
| LastName = "Álvarez", | ||
| DateOfBirth = new DateTime(2000, 1, 30, 0, 0, 0, DateTimeKind.Utc), | ||
| SquadNumber = 9, | ||
| Position = Position.CentreForward.Text, | ||
| AbbrPosition = Position.CentreForward.Abbr, | ||
| Team = "Manchester City", | ||
| League = "Premier League", | ||
| Starting11 = true, | ||
| } | ||
| ]; | ||
| var players = PlayerData.MakeStarting11(); | ||
|
|
||
| // Assign GUIDs for in-memory database testing | ||
| foreach (var player in players) | ||
| { | ||
| player.Id = Guid.NewGuid(); | ||
| } | ||
|
|
||
| return players; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Returns a specific player from the starting 11 by squad number. | ||
| /// Reuses production player data from PlayerData.MakeStarting11(). | ||
| /// </summary> | ||
| public static Player MakeFromStarting11(int squadNumber) | ||
| { | ||
| var player = | ||
| MakeStarting11().SingleOrDefault(player => player.SquadNumber == squadNumber) | ||
| PlayerData.MakeStarting11().SingleOrDefault(p => p.SquadNumber == squadNumber) | ||
| ?? throw new ArgumentNullException( | ||
| $"Player with Squad Number {squadNumber} not found." | ||
| ); | ||
|
Comment on lines
40
to
44
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inconsistent exception types for "not found" scenarios. Line 42 throws 📝 Proposed fix for consistency var player =
PlayerData.MakeStarting11().SingleOrDefault(p => p.SquadNumber == squadNumber)
- ?? throw new ArgumentNullException(
+ ?? throw new InvalidOperationException(
$"Player with Squad Number {squadNumber} not found."
);Apply similar changes at lines 126-128 and 152-154. Also applies to: 56-61 🤖 Prompt for AI Agents |
||
|
|
||
| player.Id = Guid.NewGuid(); | ||
| return player; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Returns a new player (substitute) for testing create operations. | ||
| /// Reuses production player data from PlayerData.GetSubstitutes(). | ||
| /// </summary> | ||
| public static Player MakeNew() | ||
| { | ||
| return new() | ||
| { | ||
| FirstName = "Leandro", | ||
| MiddleName = "Daniel", | ||
| LastName = "Paredes", | ||
| DateOfBirth = new DateTime(1994, 06, 29, 0, 0, 0, DateTimeKind.Utc), | ||
| SquadNumber = 5, | ||
| Position = Position.DefensiveMidfield.Text, | ||
| AbbrPosition = Position.DefensiveMidfield.Abbr, | ||
| Team = "AS Roma", | ||
| League = "Serie A", | ||
| Starting11 = false | ||
| }; | ||
| // Get Leandro Paredes (squad number 5) from substitutes | ||
| var player = | ||
| PlayerData.GetSubstitutes().SingleOrDefault(player => player.SquadNumber == 5) | ||
| ?? throw new InvalidOperationException( | ||
| "Substitute player with squad number 5 not found." | ||
| ); | ||
|
|
||
| player.Id = Guid.NewGuid(); | ||
| return player; | ||
| } | ||
|
|
||
| /* ------------------------------------------------------------------------- | ||
|
|
@@ -243,7 +109,7 @@ public static PlayerResponseModel MakeResponseModelForCreate() | |
| public static PlayerRequestModel MakeRequestModelForRetrieve(int squadNumber) | ||
| { | ||
| var player = | ||
| MakeStarting11().SingleOrDefault(player => player.SquadNumber == squadNumber) | ||
| PlayerData.MakeStarting11().SingleOrDefault(p => p.SquadNumber == squadNumber) | ||
| ?? throw new ArgumentNullException( | ||
| $"Player with Squad Number {squadNumber} not found." | ||
| ); | ||
|
|
@@ -264,7 +130,7 @@ public static PlayerRequestModel MakeRequestModelForRetrieve(int squadNumber) | |
| public static PlayerResponseModel MakeResponseModelForRetrieve(int squadNumber) | ||
| { | ||
| var player = | ||
| MakeStarting11().SingleOrDefault(player => player.SquadNumber == squadNumber) | ||
| PlayerData.MakeStarting11().SingleOrDefault(p => p.SquadNumber == squadNumber) | ||
| ?? throw new ArgumentNullException( | ||
| $"Player with Squad Number {squadNumber} not found." | ||
| ); | ||
|
|
@@ -284,17 +150,22 @@ public static PlayerResponseModel MakeResponseModelForRetrieve(int squadNumber) | |
|
|
||
| public static List<PlayerResponseModel> MakeResponseModelsForRetrieve() => | ||
| [ | ||
| .. MakeStarting11() | ||
| .Select(player => new PlayerResponseModel | ||
| .. PlayerData | ||
| .MakeStarting11() | ||
| .Select(player => | ||
| { | ||
| FullName = | ||
| $"{player.FirstName} {(string.IsNullOrWhiteSpace(player.MiddleName) ? "" : player.MiddleName + " ")}{player.LastName}".Trim(), | ||
| Birth = $"{player.DateOfBirth:MMMM d, yyyy}", | ||
| Dorsal = player.SquadNumber, | ||
| Position = player.Position, | ||
| Club = player.Team, | ||
| League = player.League, | ||
| Starting11 = player.Starting11 ? "Yes" : "No" | ||
| player.Id = Guid.NewGuid(); | ||
| return new PlayerResponseModel | ||
| { | ||
| FullName = | ||
| $"{player.FirstName} {(string.IsNullOrWhiteSpace(player.MiddleName) ? "" : player.MiddleName + " ")}{player.LastName}".Trim(), | ||
| Birth = $"{player.DateOfBirth:MMMM d, yyyy}", | ||
| Dorsal = player.SquadNumber, | ||
| Position = player.Position, | ||
| Club = player.Team, | ||
| League = player.League, | ||
| Starting11 = player.Starting11 ? "Yes" : "No" | ||
| }; | ||
| }) | ||
| ]; | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.