From 86a5d0386f22291dceb278bf2c6d2dc8d0be192e Mon Sep 17 00:00:00 2001 From: ms Date: Thu, 7 Mar 2019 17:15:37 -0300 Subject: [PATCH 1/4] Improvement 41: add IBaseService in Domain layer --- Seed.Api/Controllers/UserController.cs | 29 +++++++++--- .../Services/Interfaces/IBaseService.cs | 44 +++++++++++++++++++ .../Services/Interfaces/IUserService.cs | 33 ++------------ Seed.Domain/Services/UserService.cs | 20 ++++++--- 4 files changed, 84 insertions(+), 42 deletions(-) create mode 100644 Seed.Domain/Services/Interfaces/IBaseService.cs diff --git a/Seed.Api/Controllers/UserController.cs b/Seed.Api/Controllers/UserController.cs index 3625538..319c1fe 100644 --- a/Seed.Api/Controllers/UserController.cs +++ b/Seed.Api/Controllers/UserController.cs @@ -42,7 +42,7 @@ public async Task GetAll() /// Guid of the user /// User for the given id /// User not found - [HttpGet("{userId}")] + [HttpGet("ById/{userId}")] [ProducesResponseType(typeof(UserDto), 200)] public async Task Get(Guid userId) { @@ -52,6 +52,25 @@ public async Task Get(Guid userId) var result = new UserDto(user); + return Ok(result); + } + + /// + /// Gets a user for the given email + /// + /// Email of the user + /// User for the given email + /// User not found + [HttpGet("ByEmail/{email}")] + [ProducesResponseType(typeof(UserDto), 200)] + public async Task Get(string email) + { + var user = await _userService.GetByEmailAsync(email); + + if (user == null) return NotFound(); + + var result = new UserDto(user); + return Ok(result); } @@ -68,12 +87,12 @@ public async Task Create([FromBody]InputUserDto user) // TODO: Fix validation attribute, it's not working as expected. if (user == null) return BadRequest(); - var userToCreate = new User + var userToCreate = new User { Email = user.Email, FirstName = user.FirstName, LastName = user.LastName, - UserName = user.UserName + UserName = user.UserName }; var result = await _userService.CreateAsync(userToCreate); @@ -95,13 +114,13 @@ public async Task Update(Guid id, [FromBody]InputUserDto user) // TODO: Fix validation attribute, it's not working as expected. if (user == null) return BadRequest(); - var userToUpdate = new User + var userToUpdate = new User { Id = id, Email = user.Email, FirstName = user.FirstName, LastName = user.LastName, - UserName = user.UserName + UserName = user.UserName }; var result = await _userService.UpdateAsync(userToUpdate); diff --git a/Seed.Domain/Services/Interfaces/IBaseService.cs b/Seed.Domain/Services/Interfaces/IBaseService.cs new file mode 100644 index 0000000..58ea062 --- /dev/null +++ b/Seed.Domain/Services/Interfaces/IBaseService.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Seed.Data.Models; + +namespace Seed.Domain.Services.Interfaces +{ + public interface IBaseService where T : BaseEntity + { + /// + /// Gets a user + /// + /// Id of the entity to be retrieved + /// A object if the entity is found, otherwise null + Task GetByIdAsync(Guid guid); + + /// + /// Creates a entity + /// + /// Entity to create + /// Created user + Task CreateAsync(T entity); + + /// + /// Deletes a entity + /// + /// Id of the entity to delete + /// Whether the entity was deleted or not + Task DeleteAsync(Guid guid); + + /// + /// Gets all the existing entities + /// + /// List with all the existing entities + Task> GetAsync(); + + /// + /// Updates a entity + /// + /// Entity to update + /// Updated entity + Task UpdateAsync(T entity); + } +} diff --git a/Seed.Domain/Services/Interfaces/IUserService.cs b/Seed.Domain/Services/Interfaces/IUserService.cs index 9ebae43..1ba00ed 100644 --- a/Seed.Domain/Services/Interfaces/IUserService.cs +++ b/Seed.Domain/Services/Interfaces/IUserService.cs @@ -8,40 +8,13 @@ namespace Seed.Domain.Services.Interfaces /// /// Service responsible of handling users /// - public interface IUserService + public interface IUserService : IBaseService { /// /// Gets a user /// - /// Id of the user to be retrieved + /// Email of the user to be retrieved /// A object if the user is found, otherwise null - Task GetByIdAsync(Guid userId); - - /// - /// Creates a user - /// - /// User to create - /// Created user - Task CreateAsync(User user); - - /// - /// Deletes a user - /// - /// Id of the user to delete - /// Whether the user was deleted or not - Task DeleteAsync(Guid userId); - - /// - /// Gets all the existing users - /// - /// List with all the existing users - Task> GetAsync(); - - /// - /// Updates a user - /// - /// User to update - /// Updated user - Task UpdateAsync(User user); + Task GetByEmailAsync(string email); } } \ No newline at end of file diff --git a/Seed.Domain/Services/UserService.cs b/Seed.Domain/Services/UserService.cs index 728cd7c..cfad8f8 100644 --- a/Seed.Domain/Services/UserService.cs +++ b/Seed.Domain/Services/UserService.cs @@ -3,6 +3,7 @@ using Seed.Data.Models; using Seed.Domain.Services.Interfaces; using System; +using System.Linq; using System.Collections.Generic; using System.Threading.Tasks; @@ -17,6 +18,11 @@ public UserService(WebApiCoreSeedContext dbContext) _dbContext = dbContext; } + public async Task GetByEmailAsync(string email) + { + return await _dbContext.Users.Where(x => x.Email == email).FirstOrDefaultAsync(); + } + public async Task GetByIdAsync(Guid userId) { return await _dbContext.Users.FindAsync(userId); @@ -48,10 +54,10 @@ public async Task UpdateAsync(User user) userToUpdate.FirstName = user.FirstName; userToUpdate.LastName = user.LastName; userToUpdate.UserName = user.UserName; - userToUpdate.UpdatedOn = DateTime.Now; - - await _dbContext.SaveChangesAsync(); - + userToUpdate.UpdatedOn = DateTime.Now; + + await _dbContext.SaveChangesAsync(); + return userToUpdate; } @@ -63,9 +69,9 @@ public async Task DeleteAsync(Guid userId) _dbContext.Users.Remove(userToDelete); - var result = await _dbContext.SaveChangesAsync(); - - return result > 0; + var result = await _dbContext.SaveChangesAsync(); + + return result > 0; } } } From 4a6d59a1c1bfac6a534e81177860534f9f4ed048 Mon Sep 17 00:00:00 2001 From: ms Date: Thu, 7 Mar 2019 17:31:01 -0300 Subject: [PATCH 2/4] Fixing unit tests. --- .../Controllers/UserControllerTests.cs | 54 ++++++++++++++----- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/Seed.Api.IntegrationTests/Controllers/UserControllerTests.cs b/Seed.Api.IntegrationTests/Controllers/UserControllerTests.cs index a8a0893..c932ca8 100644 --- a/Seed.Api.IntegrationTests/Controllers/UserControllerTests.cs +++ b/Seed.Api.IntegrationTests/Controllers/UserControllerTests.cs @@ -75,7 +75,33 @@ public async Task Get_ReturnsOk() } // Act - var result = await _httpClient.GetAsync($"{ResouceUri}{sampleUser.Id.ToString()}"); + var result = await _httpClient.GetAsync($"{ResouceUri}ById/{sampleUser.Id.ToString()}"); + + // Assert + Assert.True(result.IsSuccessStatusCode); + Assert.Equal(HttpStatusCode.OK, result.StatusCode); + + var user = JsonConvert.DeserializeObject(await result.Content.ReadAsStringAsync()); + Assert.Equal(sampleUser.Id, user.Id); + Assert.Equal(sampleUser.FirstName, user.FirstName); + Assert.Equal(sampleUser.LastName, user.LastName); + Assert.Equal(sampleUser.UserName, user.UserName); + Assert.Equal(sampleUser.Email, user.Email); + } + + [Fact] + public async Task Get_EmailReturnsOk() + { + // Arrange + var sampleUser = GetSampleUser(); + using (var context = CreateContext()) + { + await context.Users.AddAsync(sampleUser); + await context.SaveChangesAsync(); + } + + // Act + var result = await _httpClient.GetAsync($"{ResouceUri}ByEmail/{sampleUser.Email}"); // Assert Assert.True(result.IsSuccessStatusCode); @@ -130,9 +156,9 @@ public async Task Create_ReturnsCreated() public async Task Create_ReturnsBadRequest_WhenInvalidInput() { // Arrange - var sampleUser = new InputUserDto - { - Email = "invalid-address" + var sampleUser = new InputUserDto + { + Email = "invalid-address" }; // Act @@ -147,7 +173,7 @@ public async Task Create_ReturnsBadRequest_WhenInvalidInput() public async Task Update_ReturnsNoContent() { // Arrange - var sampleUser = GetSampleUser(); + var sampleUser = GetSampleUser(); using (var context = CreateContext()) { await context.Users.AddAsync(sampleUser); @@ -163,8 +189,8 @@ public async Task Update_ReturnsNoContent() }; // Act - var result = await _httpClient.PutAsync($"{ResouceUri}{sampleUser.Id.ToString()}", CreateContent(userToUpdate)); - + var result = await _httpClient.PutAsync($"{ResouceUri}{sampleUser.Id.ToString()}", CreateContent(userToUpdate)); + // Assert Assert.True(result.IsSuccessStatusCode); Assert.Equal(HttpStatusCode.NoContent, result.StatusCode); @@ -195,10 +221,10 @@ public async Task Update_ReturnsNotFound_WhenUserNotExists() }; // Act - var result = await _httpClient.PutAsync($"{ResouceUri}{userId.ToString()}", CreateContent(userToUpdate)); - - // Assert - Assert.False(result.IsSuccessStatusCode); + var result = await _httpClient.PutAsync($"{ResouceUri}{userId.ToString()}", CreateContent(userToUpdate)); + + // Assert + Assert.False(result.IsSuccessStatusCode); Assert.Equal(HttpStatusCode.NotFound, result.StatusCode); } @@ -206,7 +232,7 @@ public async Task Update_ReturnsNotFound_WhenUserNotExists() public async Task Update_ReturnsBadRequest_WhenInputIsInvalid() { // Arrange - var sampleUser = GetSampleUser(); + var sampleUser = GetSampleUser(); using (var context = CreateContext()) { await context.Users.AddAsync(sampleUser); @@ -219,8 +245,8 @@ public async Task Update_ReturnsBadRequest_WhenInputIsInvalid() }; // Act - var result = await _httpClient.PutAsync($"{ResouceUri}{sampleUser.Id.ToString()}", CreateContent(userToUpdate)); - + var result = await _httpClient.PutAsync($"{ResouceUri}{sampleUser.Id.ToString()}", CreateContent(userToUpdate)); + // Assert Assert.False(result.IsSuccessStatusCode); Assert.Equal(HttpStatusCode.BadRequest, result.StatusCode); From c2155ba4a22d5b3478766b3910f1bcee56a12ab9 Mon Sep 17 00:00:00 2001 From: ms Date: Thu, 7 Mar 2019 17:46:04 -0300 Subject: [PATCH 3/4] Deleting byId path to be restfull compliant. Deleting byEmail method and its test case. --- .../Controllers/UserControllerTests.cs | 28 +------------------ Seed.Api/Controllers/UserController.cs | 21 +------------- .../Services/Interfaces/IUserService.cs | 7 +---- Seed.Domain/Services/UserService.cs | 5 ---- 4 files changed, 3 insertions(+), 58 deletions(-) diff --git a/Seed.Api.IntegrationTests/Controllers/UserControllerTests.cs b/Seed.Api.IntegrationTests/Controllers/UserControllerTests.cs index c932ca8..a724b17 100644 --- a/Seed.Api.IntegrationTests/Controllers/UserControllerTests.cs +++ b/Seed.Api.IntegrationTests/Controllers/UserControllerTests.cs @@ -75,33 +75,7 @@ public async Task Get_ReturnsOk() } // Act - var result = await _httpClient.GetAsync($"{ResouceUri}ById/{sampleUser.Id.ToString()}"); - - // Assert - Assert.True(result.IsSuccessStatusCode); - Assert.Equal(HttpStatusCode.OK, result.StatusCode); - - var user = JsonConvert.DeserializeObject(await result.Content.ReadAsStringAsync()); - Assert.Equal(sampleUser.Id, user.Id); - Assert.Equal(sampleUser.FirstName, user.FirstName); - Assert.Equal(sampleUser.LastName, user.LastName); - Assert.Equal(sampleUser.UserName, user.UserName); - Assert.Equal(sampleUser.Email, user.Email); - } - - [Fact] - public async Task Get_EmailReturnsOk() - { - // Arrange - var sampleUser = GetSampleUser(); - using (var context = CreateContext()) - { - await context.Users.AddAsync(sampleUser); - await context.SaveChangesAsync(); - } - - // Act - var result = await _httpClient.GetAsync($"{ResouceUri}ByEmail/{sampleUser.Email}"); + var result = await _httpClient.GetAsync($"{ResouceUri}{sampleUser.Id.ToString()}"); // Assert Assert.True(result.IsSuccessStatusCode); diff --git a/Seed.Api/Controllers/UserController.cs b/Seed.Api/Controllers/UserController.cs index 319c1fe..1113a64 100644 --- a/Seed.Api/Controllers/UserController.cs +++ b/Seed.Api/Controllers/UserController.cs @@ -42,7 +42,7 @@ public async Task GetAll() /// Guid of the user /// User for the given id /// User not found - [HttpGet("ById/{userId}")] + [HttpGet("{userId}")] [ProducesResponseType(typeof(UserDto), 200)] public async Task Get(Guid userId) { @@ -52,25 +52,6 @@ public async Task Get(Guid userId) var result = new UserDto(user); - return Ok(result); - } - - /// - /// Gets a user for the given email - /// - /// Email of the user - /// User for the given email - /// User not found - [HttpGet("ByEmail/{email}")] - [ProducesResponseType(typeof(UserDto), 200)] - public async Task Get(string email) - { - var user = await _userService.GetByEmailAsync(email); - - if (user == null) return NotFound(); - - var result = new UserDto(user); - return Ok(result); } diff --git a/Seed.Domain/Services/Interfaces/IUserService.cs b/Seed.Domain/Services/Interfaces/IUserService.cs index 1ba00ed..225ae5b 100644 --- a/Seed.Domain/Services/Interfaces/IUserService.cs +++ b/Seed.Domain/Services/Interfaces/IUserService.cs @@ -10,11 +10,6 @@ namespace Seed.Domain.Services.Interfaces /// public interface IUserService : IBaseService { - /// - /// Gets a user - /// - /// Email of the user to be retrieved - /// A object if the user is found, otherwise null - Task GetByEmailAsync(string email); + } } \ No newline at end of file diff --git a/Seed.Domain/Services/UserService.cs b/Seed.Domain/Services/UserService.cs index cfad8f8..f05f67e 100644 --- a/Seed.Domain/Services/UserService.cs +++ b/Seed.Domain/Services/UserService.cs @@ -18,11 +18,6 @@ public UserService(WebApiCoreSeedContext dbContext) _dbContext = dbContext; } - public async Task GetByEmailAsync(string email) - { - return await _dbContext.Users.Where(x => x.Email == email).FirstOrDefaultAsync(); - } - public async Task GetByIdAsync(Guid userId) { return await _dbContext.Users.FindAsync(userId); From 7c2fb56d183a52446d3004e01589972ab264cfe0 Mon Sep 17 00:00:00 2001 From: ms Date: Tue, 12 Mar 2019 01:31:53 -0300 Subject: [PATCH 4/4] wip --- Seed.Api/Startup.cs | 26 ++- Seed.Data/EF/DatabaseSeed.cs | 12 +- Seed.Data/EF/UserContext.cs | 21 ++ Seed.Data/EF/WebApiCoreSeedContext.cs | 20 +- .../Services/UserServiceTests.cs | 208 +++++++++--------- Seed.Domain/Services/BaseService.cs | 55 +++++ .../Services/Interfaces/IUserService.cs | 8 +- Seed.Domain/Services/UserService.cs | 47 +--- 8 files changed, 220 insertions(+), 177 deletions(-) create mode 100644 Seed.Data/EF/UserContext.cs create mode 100644 Seed.Domain/Services/BaseService.cs diff --git a/Seed.Api/Startup.cs b/Seed.Api/Startup.cs index 08c7b77..ef4e6ca 100644 --- a/Seed.Api/Startup.cs +++ b/Seed.Api/Startup.cs @@ -9,6 +9,7 @@ using Seed.Api.Filters; using Seed.Api.Middleware; using Seed.Data.EF; +using Seed.Data.Models; using Seed.Domain.Services; using Seed.Domain.Services.Interfaces; using Seed.Infrastructure.AuthZero; @@ -38,7 +39,7 @@ public Startup(IHostingEnvironment env) // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { - services.AddDbContext(options => options.UseInMemoryDatabase(Environment.MachineName)); + services.AddDbContext>(options => options.UseInMemoryDatabase(Environment.MachineName)); // Add framework services. services.AddMvc(); @@ -76,38 +77,39 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(sp => new AuthZeroClient(sp.GetRequiredService(), Configuration["auth0:NonInteractiveClientId"], Configuration["auth0:NonInteractiveClientSecret"], Configuration["auth0:domain"])); services.AddTransient(sp => new AuthZeroService(sp.GetRequiredService())); + services.AddSingleton(sp => new UserContext(options,sp.GetRequiredService>())); // Register Services - services.AddTransient(sp => new UserService(sp.GetRequiredService())); + services.AddTransient(sp => new UserService(sp.GetRequiredService())); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, WebApiCoreSeedContext dbContext) + public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, UserContext userContext) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); app.UseMiddleware(typeof(ErrorHandlingMiddleware)); app.UseMiddleware(typeof(AuthorizationMiddleware)); - app.UseSwagger(); - - // Enable middleware to serve Swagger UI (HTML, JS, CSS, etc.), specifying the Swagger JSON endpoint. + app.UseSwagger(); + + // Enable middleware to serve Swagger UI (HTML, JS, CSS, etc.), specifying the Swagger JSON endpoint. app.UseSwaggerUI(c => { // Sets Swagger UI route on root, "GET {baseUrl}/". c.RoutePrefix = string.Empty; c.SwaggerEndpoint("/swagger/v1/swagger.json", ".NET Core API Seed"); - }); - + }); + app.UseMvc(); - DatabaseSeed.Initialize(dbContext); + DatabaseSeed.Initialize(userContext); } private static Info GetSwaggerMetadata() { - return new Info - { - Title = ".NET Core API Seed", + return new Info + { + Title = ".NET Core API Seed", Version = "v1", Description = "Seed for an API using .NET Core", TermsOfService = "https://github.com/MakingSense/WebApiCore-Seed", diff --git a/Seed.Data/EF/DatabaseSeed.cs b/Seed.Data/EF/DatabaseSeed.cs index 235e921..eae7070 100644 --- a/Seed.Data/EF/DatabaseSeed.cs +++ b/Seed.Data/EF/DatabaseSeed.cs @@ -12,22 +12,22 @@ public static class DatabaseSeed /// /// Initializes a with sample Data /// - /// Context to be initialized with sample data - public static void Initialize(WebApiCoreSeedContext dbContext) + /// Context to be initialized with sample data + public static void Initialize(UserContext userContext) { - dbContext.Database.EnsureCreated(); + userContext.Database.EnsureCreated(); - if (!dbContext.Users.Any()) + if (!userContext.Users.Any()) { var users = new[] { new User { CreatedOn = DateTime.Now, Email = "noreply@makingsense.com", FirstName = "John", LastName = "Doe", UserName = "JohnDoe" }, }; - dbContext.Users.AddRange(users); + userContext.Users.AddRange(users); } - dbContext.SaveChanges(); + userContext.SaveChanges(); } } } diff --git a/Seed.Data/EF/UserContext.cs b/Seed.Data/EF/UserContext.cs new file mode 100644 index 0000000..0c0243c --- /dev/null +++ b/Seed.Data/EF/UserContext.cs @@ -0,0 +1,21 @@ +using Microsoft.EntityFrameworkCore; +using Seed.Data.Models; + +namespace Seed.Data.EF +{ + public class UserContext : WebApiCoreSeedContext + { + public DbSet Users; + + public UserContext(DbContextOptions options, DbSet users) : base(options, users) + { + Users = users; + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + // Table names should be singular but DbSet properties should be plural. + modelBuilder.Entity().ToTable("User").HasIndex(x => x.UserName).IsUnique(); + } + } +} diff --git a/Seed.Data/EF/WebApiCoreSeedContext.cs b/Seed.Data/EF/WebApiCoreSeedContext.cs index c8ac451..d3cd365 100644 --- a/Seed.Data/EF/WebApiCoreSeedContext.cs +++ b/Seed.Data/EF/WebApiCoreSeedContext.cs @@ -3,7 +3,7 @@ namespace Seed.Data.EF { - public class WebApiCoreSeedContext : DbContext + public class WebApiCoreSeedContext : DbContext where T : BaseEntity { /// /// Initializes a new instance of the class. @@ -11,20 +11,12 @@ public class WebApiCoreSeedContext : DbContext /// DbContextOptions parameter is required by AspNet core initialization /// /// Options used to create this instance - public WebApiCoreSeedContext(DbContextOptions options) : base(options) { } - - /// - /// Initializes a new instance of the class without parameters. - /// - public WebApiCoreSeedContext() : base() { } - - /// All users registered on WebApiCoreSeed database - public virtual DbSet Users { get; set; } - - protected override void OnModelCreating(ModelBuilder modelBuilder) + public WebApiCoreSeedContext(DbContextOptions options, DbSet entities) : base(options) { - // Table names should be singular but DbSet properties should be plural. - modelBuilder.Entity().ToTable("User").HasIndex(x => x.UserName).IsUnique(); + Entities = entities; } + + /// All entities registered on WebApiCoreSeed database + public virtual DbSet Entities { get; } } } diff --git a/Seed.Domain.Tests/Services/UserServiceTests.cs b/Seed.Domain.Tests/Services/UserServiceTests.cs index efd207b..e9273f8 100644 --- a/Seed.Domain.Tests/Services/UserServiceTests.cs +++ b/Seed.Domain.Tests/Services/UserServiceTests.cs @@ -1,9 +1,9 @@ using Seed.Data.EF; -using Seed.Data.Models; +using Seed.Data.Models; using Seed.Domain.Services; using System; -using System.Collections.Generic; -using System.Linq; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Xunit; @@ -13,23 +13,23 @@ public class UserServiceTests { [Fact] public async Task GetByIdAsync_ReturnsUser() - { - // Arrange - var dbContextOptions = DbContextHelper.GetOptions(); - var user = GetSampleUser(); - - using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) - { - await dbContext.Users.AddAsync(user); - await dbContext.SaveChangesAsync(); + { + // Arrange + var dbContextOptions = DbContextHelper.GetOptions(); + var user = GetSampleUser(); + + using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) + { + await dbContext.Users.AddAsync(user); + await dbContext.SaveChangesAsync(); } // Act User result; - using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) - { - var userService = new UserService(dbContext); - result = await userService.GetByIdAsync(user.Id); + using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) + { + var userService = new UserService(dbContext); + result = await userService.GetByIdAsync(user.Id); } // Assert @@ -38,16 +38,16 @@ public async Task GetByIdAsync_ReturnsUser() [Fact] public async Task GetByIdAsync_ReturnsNull_WhenNotExists() - { - // Arrange + { + // Arrange var dbContextOptions = DbContextHelper.GetOptions(); // Act User result; - using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) - { - var userService = new UserService(dbContext); - result = await userService.GetByIdAsync(Guid.NewGuid()); + using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) + { + var userService = new UserService(dbContext); + result = await userService.GetByIdAsync(Guid.NewGuid()); } // Assert @@ -56,58 +56,58 @@ public async Task GetByIdAsync_ReturnsNull_WhenNotExists() [Fact] public async Task GetAsync_ReturnsUsers() - { - // Arrange - var dbContextOptions = DbContextHelper.GetOptions(); - var users = new List - { - GetSampleUser(), - GetSampleUser(), - GetSampleUser() - }; - - using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) - { - await dbContext.Users.AddRangeAsync(users); - await dbContext.SaveChangesAsync(); + { + // Arrange + var dbContextOptions = DbContextHelper.GetOptions(); + var users = new List + { + GetSampleUser(), + GetSampleUser(), + GetSampleUser() + }; + + using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) + { + await dbContext.Users.AddRangeAsync(users); + await dbContext.SaveChangesAsync(); } // Act List result; - using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) - { - var userService = new UserService(dbContext); - result = await userService.GetAsync(); + using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) + { + var userService = new UserService(dbContext); + result = await userService.GetAsync(); } // Assert Assert.Equal(users.Count, result.Count); - foreach (var user in result) - { - var expected = users.SingleOrDefault(u => u.Id == user.Id); - AssertUser(expected, user); + foreach (var user in result) + { + var expected = users.SingleOrDefault(u => u.Id == user.Id); + AssertUser(expected, user); } } [Fact] public async Task CreateAsync_ReturnsCreatedUser() - { - // Arrange - var dbContextOptions = DbContextHelper.GetOptions(); - var user = new User - { - FirstName = "John", - LastName = "Doe", - Email = "johndoe@test.com", - UserName = "johndoe" + { + // Arrange + var dbContextOptions = DbContextHelper.GetOptions(); + var user = new User + { + FirstName = "John", + LastName = "Doe", + Email = "johndoe@test.com", + UserName = "johndoe" }; // Act User result; - using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) - { - var userService = new UserService(dbContext); - result = await userService.CreateAsync(user); + using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) + { + var userService = new UserService(dbContext); + result = await userService.CreateAsync(user); } // Assert @@ -120,32 +120,32 @@ public async Task CreateAsync_ReturnsCreatedUser() [Fact] public async Task UpdateAsync_ReturnsUpdatedUser() - { - // Arrange - var dbContextOptions = DbContextHelper.GetOptions(); - var user = GetSampleUser(); - - using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) - { - await dbContext.Users.AddAsync(user); - await dbContext.SaveChangesAsync(); + { + // Arrange + var dbContextOptions = DbContextHelper.GetOptions(); + var user = GetSampleUser(); + + using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) + { + await dbContext.Users.AddAsync(user); + await dbContext.SaveChangesAsync(); } - var toUpdate = new User - { - Id = user.Id, - FirstName = $"Updated {user.FirstName}", - LastName = $"Updated {user.LastName}", - Email = "new-email@test.com", - UserName = $"updated-{user.UserName}" + var toUpdate = new User + { + Id = user.Id, + FirstName = $"Updated {user.FirstName}", + LastName = $"Updated {user.LastName}", + Email = "new-email@test.com", + UserName = $"updated-{user.UserName}" }; // Act User result; - using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) - { - var userService = new UserService(dbContext); - result = await userService.UpdateAsync(toUpdate); + using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) + { + var userService = new UserService(dbContext); + result = await userService.UpdateAsync(toUpdate); } // Assert @@ -158,25 +158,25 @@ public async Task UpdateAsync_ReturnsUpdatedUser() [Fact] public async Task DeleteAsync_WhenUserExists_ReturnsTrue() - { - // Arrange - var dbContextOptions = DbContextHelper.GetOptions(); - var user = GetSampleUser(); - - using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) - { - await dbContext.Users.AddAsync(user); - await dbContext.SaveChangesAsync(); + { + // Arrange + var dbContextOptions = DbContextHelper.GetOptions(); + var user = GetSampleUser(); + + using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) + { + await dbContext.Users.AddAsync(user); + await dbContext.SaveChangesAsync(); } // Act bool result; User expectedUser; - using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) - { - var userService = new UserService(dbContext); - result = await userService.DeleteAsync(user.Id); - expectedUser = dbContext.Users.SingleOrDefault(u => u.Id == user.Id); + using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) + { + var userService = new UserService(dbContext); + result = await userService.DeleteAsync(user.Id); + expectedUser = dbContext.Users.SingleOrDefault(u => u.Id == user.Id); } // Assert @@ -186,28 +186,28 @@ public async Task DeleteAsync_WhenUserExists_ReturnsTrue() [Fact] public async Task DeleteAsync_WhenUserNotExists_ReturnsFalse() - { - // Arrange - var dbContextOptions = DbContextHelper.GetOptions(); + { + // Arrange + var dbContextOptions = DbContextHelper.GetOptions(); // Act bool result; - using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) - { - var userService = new UserService(dbContext); - result = await userService.DeleteAsync(Guid.NewGuid()); + using (var dbContext = new WebApiCoreSeedContext(dbContextOptions)) + { + var userService = new UserService(dbContext); + result = await userService.DeleteAsync(Guid.NewGuid()); } // Assert Assert.False(result); } - private void AssertUser(User expected, User actual) - { - Assert.Equal(expected.FirstName, actual.FirstName); - Assert.Equal(expected.LastName, actual.LastName); - Assert.Equal(expected.UserName, actual.UserName); - Assert.Equal(expected.Email, actual.Email); + private void AssertUser(User expected, User actual) + { + Assert.Equal(expected.FirstName, actual.FirstName); + Assert.Equal(expected.LastName, actual.LastName); + Assert.Equal(expected.UserName, actual.UserName); + Assert.Equal(expected.Email, actual.Email); } private User GetSampleUser(Guid? id = null) diff --git a/Seed.Domain/Services/BaseService.cs b/Seed.Domain/Services/BaseService.cs new file mode 100644 index 0000000..5e2e8b8 --- /dev/null +++ b/Seed.Domain/Services/BaseService.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Seed.Data.EF; +using Seed.Data.Models; + +namespace Seed.Domain.Services +{ + public abstract class BaseService where T : BaseEntity + { + private readonly WebApiCoreSeedContext _dbContext; + + public BaseService(WebApiCoreSeedContext dbContext) + { + _dbContext = dbContext; + } + + public async Task GetByIdAsync(Guid id) + { + return await _dbContext.Entities.FindAsync(id); + } + + public async Task> GetAsync() + { + return await _dbContext.Entities.ToListAsync(); + } + + public async Task CreateAsync(T entity) + { + entity.Id = Guid.NewGuid(); + entity.CreatedOn = DateTime.Now; + + await _dbContext.Entities.AddAsync(entity); + await _dbContext.SaveChangesAsync(); + + return entity; + } + + public abstract Task UpdateAsync(T entity); + + public async Task DeleteAsync(Guid id) + { + var userToDelete = await _dbContext.Entities.FindAsync(id); + + if (userToDelete == null) return false; + + _dbContext.Entities.Remove(userToDelete); + + var result = await _dbContext.SaveChangesAsync(); + + return result > 0; + } + } +} diff --git a/Seed.Domain/Services/Interfaces/IUserService.cs b/Seed.Domain/Services/Interfaces/IUserService.cs index 225ae5b..84fe0c4 100644 --- a/Seed.Domain/Services/Interfaces/IUserService.cs +++ b/Seed.Domain/Services/Interfaces/IUserService.cs @@ -1,6 +1,4 @@ using Seed.Data.Models; -using System; -using System.Collections.Generic; using System.Threading.Tasks; namespace Seed.Domain.Services.Interfaces @@ -10,6 +8,10 @@ namespace Seed.Domain.Services.Interfaces /// public interface IUserService : IBaseService { - + /// + /// Gets a user + /// + /// Email of the user to be retrieved + /// A object if the user is found, otherwise null } } \ No newline at end of file diff --git a/Seed.Domain/Services/UserService.cs b/Seed.Domain/Services/UserService.cs index f05f67e..598ccca 100644 --- a/Seed.Domain/Services/UserService.cs +++ b/Seed.Domain/Services/UserService.cs @@ -9,39 +9,23 @@ namespace Seed.Domain.Services { - public class UserService : IUserService + public class UserService : BaseService, IUserService { - private readonly WebApiCoreSeedContext _dbContext; + private readonly UserContext _userContext; - public UserService(WebApiCoreSeedContext dbContext) + public UserService(UserContext dbContext) : base(dbContext) { - _dbContext = dbContext; + _userContext = dbContext; } - public async Task GetByIdAsync(Guid userId) + public async Task GetByEmailAsync(string email) { - return await _dbContext.Users.FindAsync(userId); + return await _userContext.Users.Where(x => x.Email == email).FirstOrDefaultAsync(); } - public async Task> GetAsync() + public override async Task UpdateAsync(User user) { - return await _dbContext.Users.ToListAsync(); - } - - public async Task CreateAsync(User user) - { - user.Id = Guid.NewGuid(); - user.CreatedOn = DateTime.Now; - - await _dbContext.Users.AddAsync(user); - await _dbContext.SaveChangesAsync(); - - return user; - } - - public async Task UpdateAsync(User user) - { - var userToUpdate = await _dbContext.Users.FindAsync(user.Id); + var userToUpdate = await _userContext.Users.FindAsync(user.Id); if (userToUpdate == null) return null; @@ -51,22 +35,9 @@ public async Task UpdateAsync(User user) userToUpdate.UserName = user.UserName; userToUpdate.UpdatedOn = DateTime.Now; - await _dbContext.SaveChangesAsync(); + await _userContext.SaveChangesAsync(); return userToUpdate; } - - public async Task DeleteAsync(Guid userId) - { - var userToDelete = await _dbContext.Users.FindAsync(userId); - - if (userToDelete == null) return false; - - _dbContext.Users.Remove(userToDelete); - - var result = await _dbContext.SaveChangesAsync(); - - return result > 0; - } } }