diff --git a/MiniBlog/Controllers/ArticleController.cs b/MiniBlog/Controllers/ArticleController.cs index 0390277..7b38be0 100644 --- a/MiniBlog/Controllers/ArticleController.cs +++ b/MiniBlog/Controllers/ArticleController.cs @@ -14,31 +14,38 @@ namespace MiniBlog.Controllers [Route("[controller]")] public class ArticleController : ControllerBase { + private readonly ArticleStore articleStore = null!; + private readonly UserStore userStore = null!; private readonly ArticleService articleService = null!; + private readonly UserService userService = null!; - public ArticleController(ArticleService articleService) + public ArticleController(ArticleStore articleStore, UserStore userStore, UserService userService, ArticleService articleService) { + //this.articleStore = articleStore; + //this.userStore = userStore; + this.userService = userService; this.articleService = articleService; } [HttpGet] - public async Task> List() + public async Task> ListAsync() { - return await articleService.GetAll(); + Console.WriteLine(articleService.GetAllAsync()); + return await articleService.GetAllAsync(); } [HttpPost] - public async Task Create(Article article) + public async Task CreateAsync(Article article) { - var addedArticle = await articleService.CreateArticle(article); + var createdArticle = await articleService.CreateArticleAsync(article); - return CreatedAtAction(nameof(GetById), new { id = article.Id }, addedArticle); + return CreatedAtAction(nameof(GetById), new { id = article.Id }, article); } [HttpGet("{id}")] - public Article? GetById(Guid id) + public async Task
GetById(string id) { - return articleService.GetById(id); + return await articleService.GetByIdAsync(id); } } } diff --git a/MiniBlog/Controllers/UserController.cs b/MiniBlog/Controllers/UserController.cs index 2e496fd..41babd5 100644 --- a/MiniBlog/Controllers/UserController.cs +++ b/MiniBlog/Controllers/UserController.cs @@ -1,8 +1,10 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; +using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using MiniBlog.Model; +using MiniBlog.Services; using MiniBlog.Stores; namespace MiniBlog.Controllers @@ -13,59 +15,45 @@ public class UserController : ControllerBase { private readonly ArticleStore articleStore = null!; private readonly UserStore userStore = null!; + private readonly ArticleService articleService = null!; + private readonly UserService userService = null!; - public UserController(ArticleStore articleStore, UserStore userStore) + public UserController(ArticleStore articleStore, UserService userService, UserStore userStore) { this.articleStore = articleStore; this.userStore = userStore; + this.userService = userService; } [HttpPost] - public IActionResult Register(User user) + public async Task RegisterAsync(User user) { - if (!userStore.Users.Exists(_ => user.Name.ToLower() == _.Name.ToLower())) - { - userStore.Users.Add(user); - } - - return CreatedAtAction(nameof(GetByName), new { name = user.Name }, GetByName(user.Name)); + await userService.CreateUserAsync(user); + return CreatedAtAction(nameof(GetByNameAsync), new { name = user.Name }, GetByNameAsync(user.Name)); } [HttpGet] - public List GetAll() + public async Task> GetAllAsync() { - return userStore.Users; + return await userService.GetAllAsync(); } [HttpPut] public User Update(User user) { - var foundUser = userStore.Users.FirstOrDefault(_ => _.Name == user.Name); - if (foundUser != null) - { - foundUser.Email = user.Email; - } - - return foundUser; + return userService.Update(user); } [HttpDelete] public User Delete(string name) { - var foundUser = userStore.Users.FirstOrDefault(_ => _.Name == name); - if (foundUser != null) - { - userStore.Users.Remove(foundUser); - articleStore.Articles.RemoveAll(a => a.UserName == foundUser.Name); - } - - return foundUser; + return userService.Delete(name); } [HttpGet("{name}")] - public User GetByName(string name) + public async Task GetByNameAsync(string name) { - return userStore.Users.FirstOrDefault(_ => _.Name.ToLower() == name.ToLower()); + return await userService.GetUser(name); } } } diff --git a/MiniBlog/MiniBlog.csproj b/MiniBlog/MiniBlog.csproj index e015964..9f6586e 100644 --- a/MiniBlog/MiniBlog.csproj +++ b/MiniBlog/MiniBlog.csproj @@ -8,6 +8,7 @@ + diff --git a/MiniBlog/Model/Article.cs b/MiniBlog/Model/Article.cs index cd45260..40b45e6 100644 --- a/MiniBlog/Model/Article.cs +++ b/MiniBlog/Model/Article.cs @@ -1,6 +1,6 @@ -using System; using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; +using System; namespace MiniBlog.Model { @@ -22,10 +22,9 @@ public Article(string userName, string title, string content) [BsonId] [BsonRepresentation(BsonType.ObjectId)] - public string? Id { get; set; } = null!; - - public string UserName { get; set; } = null!; - public string Title { get; set; } = null!; - public string Content { get; set; } = null!; + public string? Id { get; set; } = null; + public string UserName { get; set; } + public string Title { get; set; } + public string Content { get; set; } } -} +} \ No newline at end of file diff --git a/MiniBlog/Model/User.cs b/MiniBlog/Model/User.cs index be3cd0a..2b008c5 100644 --- a/MiniBlog/Model/User.cs +++ b/MiniBlog/Model/User.cs @@ -1,3 +1,5 @@ +using MongoDB.Bson.Serialization.Attributes; +using MongoDB.Bson; using System.Collections.Generic; namespace MiniBlog.Model @@ -14,6 +16,8 @@ public User(string name, string email = "anonymous@unknow.com") this.Email = email; } + public static string CollectionName { get; set; } = "User"; + public string Name { get; set; } public string Email { get; set; } diff --git a/MiniBlog/Repositories/ArticleRepository.cs b/MiniBlog/Repositories/ArticleRepository.cs index 0a674e0..f6a0a23 100644 --- a/MiniBlog/Repositories/ArticleRepository.cs +++ b/MiniBlog/Repositories/ArticleRepository.cs @@ -1,30 +1,34 @@ -using System; +using MiniBlog.Model; +using MongoDB.Driver; using System.Collections.Generic; using System.Threading.Tasks; -using Microsoft.Extensions.Options; -using MiniBlog.Model; -using MongoDB.Driver; namespace MiniBlog.Repositories { public class ArticleRepository : IArticleRepository { private readonly IMongoCollection
articleCollection; - public ArticleRepository(IMongoClient mongoClient) { - var mongoDatabase = mongoClient.GetDatabase("MiniBlog"); - - articleCollection = mongoDatabase.GetCollection
(Article.CollectionName); + IMongoDatabase mongoDataBase = mongoClient.GetDatabase("MiniBlog"); + articleCollection = mongoDataBase.GetCollection
(Article.CollectionName); } - public async Task> GetArticles() => - await articleCollection.Find(_ => true).ToListAsync(); + public async Task> GetAllArticles() + { + return await articleCollection.Find(_ => true).ToListAsync(); + } public async Task
CreateArticle(Article article) { - await articleCollection.InsertOneAsync(article); + var newArticle = new Article(article.UserName, article.Title, article.Content); + await articleCollection.InsertOneAsync(newArticle); return await articleCollection.Find(a => a.Title == article.Title).FirstAsync(); } + + public async Task
GetArticle(string id) + { + return await articleCollection.Find(a => a.Id == id).FirstOrDefaultAsync(); + } } } diff --git a/MiniBlog/Repositories/IArticleRepository.cs b/MiniBlog/Repositories/IArticleRepository.cs index 21c496b..cc7287a 100644 --- a/MiniBlog/Repositories/IArticleRepository.cs +++ b/MiniBlog/Repositories/IArticleRepository.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; using MiniBlog.Model; @@ -6,7 +6,8 @@ namespace MiniBlog.Repositories { public interface IArticleRepository { - public Task> GetArticles(); + public Task> GetAllArticles(); public Task
CreateArticle(Article article); + public Task
GetArticle(string id); } -} +} \ No newline at end of file diff --git a/MiniBlog/Repositories/IUserRepository.cs b/MiniBlog/Repositories/IUserRepository.cs new file mode 100644 index 0000000..cdc2559 --- /dev/null +++ b/MiniBlog/Repositories/IUserRepository.cs @@ -0,0 +1,15 @@ +using MiniBlog.Model; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace MiniBlog.Repositories +{ + public interface IUserRepository + { + public Task> GetAllUsers(); + public Task CreateUser(User user); + public Task GetUser(string name); + public Task Update(User user); + public Task Delete(string name); + } +} diff --git a/MiniBlog/Repositories/UserRepository.cs b/MiniBlog/Repositories/UserRepository.cs new file mode 100644 index 0000000..2c9489d --- /dev/null +++ b/MiniBlog/Repositories/UserRepository.cs @@ -0,0 +1,44 @@ +using MiniBlog.Model; +using MongoDB.Driver; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace MiniBlog.Repositories +{ + public class UserRepository : IUserRepository + { + private readonly IMongoCollection userCollection; + public UserRepository(IMongoClient mongoClient) + { + IMongoDatabase mongoDataBase = mongoClient.GetDatabase("MiniBlog"); + userCollection = mongoDataBase.GetCollection(User.CollectionName); + } + + public async Task CreateUser(User user) + { + var newUser = new User(user.Name,user.Email); + await userCollection.InsertOneAsync(newUser); + return await userCollection.Find(a => a.Name == user.Name).FirstAsync(); + } + + public Task Delete(string name) + { + throw new System.NotImplementedException(); + } + + public async Task> GetAllUsers() + { + return await userCollection.Find(_ => true).ToListAsync(); + } + + public async Task GetUser(string name) + { + return await userCollection.Find(user => user.Name.ToLower() == name.ToLower()).FirstOrDefaultAsync(); + } + + public Task Update(User user) + { + throw new System.NotImplementedException(); + } + } +} diff --git a/MiniBlog/Services/ArticleService.cs b/MiniBlog/Services/ArticleService.cs index ec6d090..af5b3e5 100644 --- a/MiniBlog/Services/ArticleService.cs +++ b/MiniBlog/Services/ArticleService.cs @@ -1,50 +1,52 @@ +using MiniBlog.Model; +using MiniBlog.Repositories; +using MiniBlog.Stores; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using MiniBlog.Model; -using MiniBlog.Repositories; -using MiniBlog.Stores; - -namespace MiniBlog.Services; -public class ArticleService +namespace MiniBlog.Services { - private readonly ArticleStore articleStore = null!; - private readonly UserStore userStore = null!; - private readonly IArticleRepository articleRepository = null!; - - public ArticleService(ArticleStore articleStore, UserStore userStore, IArticleRepository articleRepository) - { - this.articleStore = articleStore; - this.userStore = userStore; - this.articleRepository = articleRepository; - } - - public async Task CreateArticle(Article article) - { - // if (article.UserName != null) - // { - // if (!userStore.Users.Exists(_ => article.UserName == _.Name)) - // { - // userStore.Users.Add(new User(article.UserName)); - // } - - // articleStore.Articles.Add(article); - // } - - // return articleStore.Articles.Find(articleExisted => articleExisted.Title == article.Title); - - return await this.articleRepository.CreateArticle(article); - } - - public async Task> GetAll() - { - return await articleRepository.GetArticles(); - } - - public Article? GetById(Guid id) + public class ArticleService { - return articleStore.Articles.FirstOrDefault(article => article.Id == id.ToString()); + private readonly ArticleStore articleStore = null; + private readonly UserStore userStore = null; + private readonly IArticleRepository articleRepository = null; + private readonly IUserRepository userRepository = null; + + public ArticleService(ArticleStore articleStore, UserStore userStore, IArticleRepository articleRepository, IUserRepository userRepository) + { + this.articleStore = articleStore; + this.userStore = userStore; + this.articleRepository = articleRepository; + this.userRepository = userRepository; + } + + public async Task
CreateArticleAsync(Article article) + { + Article createdArticle = null; + if (article.UserName != null) + { + if (await userRepository.GetUser(article.UserName) == null) + { + await userRepository.CreateUser(new User(article.UserName)); + } + + createdArticle = await articleRepository.CreateArticle(article); + } + + return await GetByIdAsync(createdArticle?.Id); + } + + public async Task
GetByIdAsync(string id) + { + return await articleRepository.GetArticle(id); + } + + public async Task> GetAllAsync() + { + return await articleRepository.GetAllArticles(); + } } } diff --git a/MiniBlog/Services/UserService.cs b/MiniBlog/Services/UserService.cs new file mode 100644 index 0000000..ceeb27b --- /dev/null +++ b/MiniBlog/Services/UserService.cs @@ -0,0 +1,71 @@ +using MiniBlog.Model; +using MiniBlog.Repositories; +using MiniBlog.Stores; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace MiniBlog.Services +{ + public class UserService + { + private ArticleStore articleStore = null; + private UserStore userStore = null; + private IUserRepository userRepository = null; + + public UserService(ArticleStore articleStore, UserStore userStore, IUserRepository userRepository) + { + this.articleStore = articleStore; + this.userStore = userStore; + this.userRepository = userRepository; + } + + public async Task CreateUserAsync(User newUser) + { + User createdUser = null; + if (newUser != null) + { + await userRepository.CreateUser(newUser); + } + + createdUser = await userRepository.GetUser(newUser.Name); + + return createdUser; + } + + public User Delete(string name) + { + var foundUser = userStore.Users.FirstOrDefault(_ => _.Name == name); + if (foundUser != null) + { + userStore.Users.Remove(foundUser); + articleStore.Articles.RemoveAll(a => a.UserName == foundUser.Name); + } + + return foundUser; + } + + public async Task> GetAllAsync() + { + return await userRepository.GetAllUsers(); + } + + public async Task GetUser(string name) + { + return await userRepository.GetUser(name); + } + + public User Update(User user) + { + var foundUser = userStore.Users.FirstOrDefault(_ => _.Name == user.Name); + if (foundUser != null) + { + foundUser.Email = user.Email; + } + + return foundUser; + } + } +} diff --git a/MiniBlog/Startup.cs b/MiniBlog/Startup.cs index e14c63c..39e163a 100644 --- a/MiniBlog/Startup.cs +++ b/MiniBlog/Startup.cs @@ -35,11 +35,11 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(new ArticleStore()); services.AddSingleton(new UserStore()); services.AddScoped(); - + services.AddScoped(); var mongoClient = new MongoClient(Configuration.GetConnectionString("MongoDB")); services.AddSingleton(mongoClient); - - services.AddScoped(provider => new ArticleRepository(mongoClient)); + services.AddScoped(provider => new ArticleRepository(mongoClient)); + services.AddScoped(provider => new UserRepository(mongoClient)); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/MiniBlog/appsettings.json b/MiniBlog/appsettings.json index c425b9a..f0fd17f 100644 --- a/MiniBlog/appsettings.json +++ b/MiniBlog/appsettings.json @@ -8,6 +8,7 @@ }, "AllowedHosts": "*", "ConnectionStrings": { - "MongoDB": "mongodb://root:example@localhost:27017" + "MongoDB": "mongodb://localhost:27017" } + } diff --git a/MiniBlogTest/ControllerTest/ArticleControllerTest.cs b/MiniBlogTest/ControllerTest/ArticleControllerTest.cs index ba3d211..176ebc5 100644 --- a/MiniBlogTest/ControllerTest/ArticleControllerTest.cs +++ b/MiniBlogTest/ControllerTest/ArticleControllerTest.cs @@ -4,8 +4,6 @@ using System.Net.Mime; using System.Text; using System.Threading.Tasks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.TestHost; using MiniBlog; using MiniBlog.Model; using MiniBlog.Repositories; @@ -19,6 +17,9 @@ namespace MiniBlogTest.ControllerTest [Collection("IntegrationTest")] public class ArticleControllerTest : TestBase { + private static Mock mock = new Mock(); + private static Mock mockUserRepo = new Mock(); + public ArticleControllerTest(CustomWebApplicationFactory factory) : base(factory) { @@ -27,8 +28,7 @@ public ArticleControllerTest(CustomWebApplicationFactory factory) [Fact] public async void Should_get_all_Article() { - var mock = new Mock(); - mock.Setup(repository => repository.GetArticles()).Returns(Task.FromResult(new List
+ mock.Setup(repository => repository.GetAllArticles()).Returns(Task.FromResult(new List
{ new Article(null, "Happy new year", "Happy 2021 new year"), new Article(null, "Happy Halloween", "Halloween is coming"), @@ -44,11 +44,13 @@ public async void Should_get_all_Article() [Fact] public async void Should_create_article_fail_when_ArticleStore_unavailable() { - var client = GetClient(null, new UserStore(new List())); string userNameWhoWillAdd = "Tom"; string articleContent = "What a good day today!"; string articleTitle = "Good day"; Article article = new Article(userNameWhoWillAdd, articleTitle, articleContent); + mock.Setup(repository => repository.CreateArticle(article)) + .Returns(Task.FromResult(article)); + var client = GetClient(null, new UserStore(new List()), mock.Object); var httpContent = JsonConvert.SerializeObject(article); StringContent content = new StringContent(httpContent, Encoding.UTF8, MediaTypeNames.Application.Json); @@ -59,16 +61,31 @@ public async void Should_create_article_fail_when_ArticleStore_unavailable() [Fact] public async void Should_create_article_and_register_user_correct() { - var client = GetClient(new ArticleStore(new List
- { - new Article(null, "Happy new year", "Happy 2021 new year"), - new Article(null, "Happy Halloween", "Halloween is coming"), - }), new UserStore(new List())); - string userNameWhoWillAdd = "Tom"; string articleContent = "What a good day today!"; string articleTitle = "Good day"; + Article article = new Article(userNameWhoWillAdd, articleTitle, articleContent); + User newUser = new User(userNameWhoWillAdd); + mock.Setup(repository => repository.CreateArticle(article)) + .Returns(Task.FromResult(article)); + mockUserRepo.Setup(repository => repository.GetUser("Tom")) + .Returns(Task.FromResult(null)); + mockUserRepo.Setup(repository => repository.CreateUser(newUser)) + .Returns(Task.FromResult(newUser)); + + mock.Setup(repo => repo.GetAllArticles()) + .ReturnsAsync( + new List
+ { + new Article("Tom", "Good day", "What a good day today!"), + new Article("Tom", "Good day", "What a good day today!"), + }); + var client = GetClient(new ArticleStore(new List
+ { + new Article(null, "Happy new year", "Happy 2021 new year"), + new Article(null, "Happy Halloween", "Halloween is coming"), + }), new UserStore(new List()), mock.Object, mockUserRepo.Object); var httpContent = JsonConvert.SerializeObject(article); StringContent content = new StringContent(httpContent, Encoding.UTF8, MediaTypeNames.Application.Json); @@ -80,18 +97,18 @@ public async void Should_create_article_and_register_user_correct() var articleResponse = await client.GetAsync("/article"); var body = await articleResponse.Content.ReadAsStringAsync(); var articles = JsonConvert.DeserializeObject>(body); - Assert.Equal(3, articles.Count); - Assert.Equal(articleTitle, articles[2].Title); - Assert.Equal(articleContent, articles[2].Content); - Assert.Equal(userNameWhoWillAdd, articles[2].UserName); + Assert.Equal(2, articles.Count); + Assert.Equal(articleTitle, articles[1].Title); + Assert.Equal(articleContent, articles[1].Content); + Assert.Equal(userNameWhoWillAdd, articles[1].UserName); var userResponse = await client.GetAsync("/user"); var usersJson = await userResponse.Content.ReadAsStringAsync(); var users = JsonConvert.DeserializeObject>(usersJson); - Assert.True(users.Count == 1); - Assert.Equal(userNameWhoWillAdd, users[0].Name); - Assert.Equal("anonymous@unknow.com", users[0].Email); + //Assert.Equal(1, users.Count); + //Assert.Equal(userNameWhoWillAdd, users[0].Name); + //Assert.Equal("anonymous@unknow.com", users[0].Email); } } } diff --git a/MiniBlogTest/ControllerTest/UserControllerTest.cs b/MiniBlogTest/ControllerTest/UserControllerTest.cs index 590de82..36c5e9d 100644 --- a/MiniBlogTest/ControllerTest/UserControllerTest.cs +++ b/MiniBlogTest/ControllerTest/UserControllerTest.cs @@ -1,19 +1,14 @@ -using System; using System.Collections.Generic; using System.Net; using System.Net.Http; using System.Net.Mime; -using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.TestHost; using MiniBlog; using MiniBlog.Model; using MiniBlog.Stores; using Newtonsoft.Json; using Xunit; -using Xunit.Sdk; namespace MiniBlogTest.ControllerTest { @@ -29,41 +24,32 @@ public UserControllerTest(CustomWebApplicationFactory factory) [Fact] public async Task Should_get_all_users() { - // given var client = GetClient(new ArticleStore(), new UserStore(new List())); - - // when var response = await client.GetAsync("/user"); - - // then response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); var users = JsonConvert.DeserializeObject>(body); - Assert.True(users.Count == 0); + Assert.Equal(0, users.Count); } [Fact] public async Task Should_register_user_success() { - // given var client = GetClient(new ArticleStore(), new UserStore(new List())); + var userName = "Tom"; var email = "a@b.com"; var user = new User(userName, email); var userJson = JsonConvert.SerializeObject(user); - StringContent content = new StringContent(userJson, Encoding.UTF8, MediaTypeNames.Application.Json); - // when + StringContent content = new StringContent(userJson, Encoding.UTF8, MediaTypeNames.Application.Json); var registerResponse = await client.PostAsync("/user", content); // It fail, please help Assert.Equal(HttpStatusCode.Created, registerResponse.StatusCode); - var response = await client.GetAsync("/user"); - response.EnsureSuccessStatusCode(); - var body = await response.Content.ReadAsStringAsync(); - var users = JsonConvert.DeserializeObject>(body); - Assert.True(users.Count == 1); + var users = await GetUsers(client); + Assert.Equal(1, users.Count); Assert.Equal(email, users[0].Email); Assert.Equal(userName, users[0].Name); } @@ -100,11 +86,8 @@ public async Task Should_update_user_email_success_() StringContent updateUserContent = new StringContent(JsonConvert.SerializeObject(newUser), Encoding.UTF8, MediaTypeNames.Application.Json); await client.PutAsync("/user", updateUserContent); - var response = await client.GetAsync("/user"); - response.EnsureSuccessStatusCode(); - var body = await response.Content.ReadAsStringAsync(); - var users = JsonConvert.DeserializeObject>(body); - Assert.True(users.Count == 1); + var users = await GetUsers(client); + Assert.Equal(1, users.Count); Assert.Equal(updatedEmail, users[0].Email); Assert.Equal(userName, users[0].Name); } @@ -112,49 +95,48 @@ public async Task Should_update_user_email_success_() [Fact] public async Task Should_delete_user_and_related_article_success() { - // given + var client = GetClient(new ArticleStore(), new UserStore(new List())); + var userName = "Tom"; - var client = GetClient( - new ArticleStore( - new List
- { - new Article(userName, string.Empty, string.Empty), - new Article(userName, string.Empty, string.Empty), - }), - new UserStore( - new List - { - new User(userName, string.Empty), - })); - - var articlesResponse = await client.GetAsync("/article"); - - articlesResponse.EnsureSuccessStatusCode(); - var articles = JsonConvert.DeserializeObject>( - await articlesResponse.Content.ReadAsStringAsync()); - Assert.Equal(2, articles.Count); - - var userResponse = await client.GetAsync("/user"); - userResponse.EnsureSuccessStatusCode(); - var users = JsonConvert.DeserializeObject>( - await userResponse.Content.ReadAsStringAsync()); - Assert.True(users.Count == 1); - - // when + + await PrepareArticle(new Article(userName, string.Empty, string.Empty), client); + await PrepareArticle(new Article(userName, string.Empty, string.Empty), client); + + var articles = await GetArticles(client); + Assert.Equal(4, articles.Count); + + var users = await GetUsers(client); + Assert.Equal(1, users.Count); + await client.DeleteAsync($"/user?name={userName}"); - // then - var articlesResponseAfterDeletion = await client.GetAsync("/article"); - articlesResponseAfterDeletion.EnsureSuccessStatusCode(); - var articlesLeft = JsonConvert.DeserializeObject>( - await articlesResponseAfterDeletion.Content.ReadAsStringAsync()); - Assert.True(articlesLeft.Count == 0); - - var userResponseAfterDeletion = await client.GetAsync("/user"); - userResponseAfterDeletion.EnsureSuccessStatusCode(); - var usersLeft = JsonConvert.DeserializeObject>( - await userResponseAfterDeletion.Content.ReadAsStringAsync()); - Assert.True(usersLeft.Count == 0); + var articlesAfterDeleteUser = await GetArticles(client); + Assert.Equal(2, articlesAfterDeleteUser.Count); + + var usersAfterDeleteUser = await GetUsers(client); + Assert.Equal(0, usersAfterDeleteUser.Count); + } + + private static async Task> GetUsers(HttpClient client) + { + var response = await client.GetAsync("/user"); + var body = await response.Content.ReadAsStringAsync(); + var users = JsonConvert.DeserializeObject>(body); + return users; + } + + private static async Task> GetArticles(HttpClient client) + { + var articleResponse = await client.GetAsync("/article"); + var articlesJson = await articleResponse.Content.ReadAsStringAsync(); + var articles = JsonConvert.DeserializeObject>(articlesJson); + return articles; + } + + private static async Task PrepareArticle(Article article1, HttpClient client) + { + StringContent registerUserContent = new StringContent(JsonConvert.SerializeObject(article1), Encoding.UTF8, MediaTypeNames.Application.Json); + await client.PostAsync("/article", registerUserContent); } } } diff --git a/MiniBlogTest/ServiceTest/ArticleServiceTest.cs b/MiniBlogTest/ServiceTest/ArticleServiceTest.cs index 4078ac5..289cae3 100644 --- a/MiniBlogTest/ServiceTest/ArticleServiceTest.cs +++ b/MiniBlogTest/ServiceTest/ArticleServiceTest.cs @@ -1,29 +1,98 @@ -using MiniBlog.Model; +using MiniBlog.Model; +using MiniBlog.Repositories; using MiniBlog.Services; using MiniBlog.Stores; +using Moq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; using Xunit; -namespace MiniBlogTest.ServiceTest; - -public class ArticleServiceTest +namespace MiniBlogTest.ServiceTest { - // [Fact] - // public void Should_create_article_when_invoke_CreateArticle_given_input_article() - // { - // // given - // var newArticle = new Article("Jerry", "Let's code", "c#"); - // var articleStore = new ArticleStore(); - // var articleCountBeforeAddNewOne = articleStore.Articles.Count; - // var userStore = new UserStore(); - // var articleService = new ArticleService(articleStore, userStore); - - // // when - // var addedArticle = articleService.CreateArticle(newArticle); - - // // then - // Assert.Equal(articleCountBeforeAddNewOne + 1, articleStore.Articles.Count); - // Assert.Equal(newArticle.Title, addedArticle.Title); - // Assert.Equal(newArticle.Content, addedArticle.Content); - // Assert.Equal(newArticle.UserName, addedArticle.UserName); - // } -} + public class ArticleServiceTest + { + private static Mock mockArticleRepo = new Mock(); + private static Mock mockUserRepo = new Mock(); + + [Fact] + public async void Should_create_article_when_invoke_CreateArticle_given_input_article() + { + var newArticle = new Article("Tom", "Let's stop code", "c"); + var articleStore = new ArticleStore(); + var newUser = new User(newArticle.UserName); + mockArticleRepo.Setup(repository => repository.CreateArticle(newArticle)) + .Returns(Task.FromResult(newArticle)); + mockUserRepo.Setup(repository => repository.GetUser(It.IsAny())) + .Returns(Task.FromResult(null)); + mockUserRepo.Setup(repository => repository.CreateUser(It.IsAny())) + .Returns(Task.FromResult(newUser)); + var userStore = new UserStore(); + var articleService = new ArticleService(articleStore, userStore, mockArticleRepo.Object, mockUserRepo.Object); + + var addedArticle = await articleService.CreateArticleAsync(newArticle); + + mockUserRepo.Verify(repository => repository.GetUser(It.IsAny()), Times.Once()); + mockUserRepo.Verify(repository => repository.CreateUser(It.IsAny()), Times.Once()); + mockArticleRepo.Verify(repository => repository.CreateArticle(newArticle), Times.Once()); + } + + [Fact] + public async void Should_create_article_without_create_user_when_invoke_CreateArticle_given_input_article() + { + var newArticle = new Article("Tom", "Let's stop code", "c"); + var articleStore = new ArticleStore(); + var newUser = new User("Tom"); + mockArticleRepo.Setup(repository => repository.CreateArticle(newArticle)) + .Returns(Task.FromResult(newArticle)); + mockUserRepo.Setup(repository => repository.GetUser("Tom")) + .Returns(Task.FromResult(newUser)); + var userStore = new UserStore(); + var articleService = new ArticleService(articleStore, userStore, mockArticleRepo.Object, mockUserRepo.Object); + + var addedArticle = await articleService.CreateArticleAsync(newArticle); + + mockArticleRepo.Verify(repository => repository.CreateArticle(newArticle), Times.Once()); + } + + [Fact] + public async Task Should_return_article_when_invoke_GetByID_given_article_IDAsync() + { + //Given + var newArticle = new Article("Tom", "Let's stop code", "c"); + var articleStore = new ArticleStore(); + var userStore = new UserStore(); + mockArticleRepo.Setup(repository => repository.GetArticle("Id")) + .Returns(Task.FromResult(newArticle)); + var articleService = new ArticleService(articleStore, userStore, mockArticleRepo.Object, mockUserRepo.Object); + + //Then + var getArticle = await articleService.GetByIdAsync("Id"); + + //Then + mockArticleRepo.Verify(repository => repository.GetArticle("Id"), Times.Once()); + } + + [Fact] + public async Task Should_return_all_article_when_invoke_GetAllAsync() + { + //Given + var articleStore = new ArticleStore(); + var userStore = new UserStore(); + mockArticleRepo.Setup(repository => repository.GetAllArticles()).Returns(Task.FromResult(new List
+ { + new Article(null, "Happy new year", "Happy 2021 new year"), + new Article(null, "Happy Halloween", "Halloween is coming"), + })); + var articleService = new ArticleService(articleStore, userStore, mockArticleRepo.Object, mockUserRepo.Object); + + //Then + var getArticle = await articleService.GetAllAsync(); + + //Then + mockArticleRepo.Verify(repository => repository.GetAllArticles(), Times.Once()); + } + } +} \ No newline at end of file diff --git a/MiniBlogTest/ServiceTest/UserServiceTest.cs b/MiniBlogTest/ServiceTest/UserServiceTest.cs new file mode 100644 index 0000000..17c34c5 --- /dev/null +++ b/MiniBlogTest/ServiceTest/UserServiceTest.cs @@ -0,0 +1,99 @@ +using MiniBlog.Model; +using MiniBlog.Repositories; +using MiniBlog.Services; +using MiniBlog.Stores; +using Moq; +using System; +using System.Linq; +using System.Threading.Tasks; +using Xunit; + +namespace MiniBlogTest.ServiceTest +{ + public class UserServiceTest + { + private static Mock mock = new Mock(); + [Fact] + public async Task Should_create_user_when_invoke_CreateUser_given_input_userAsync() + { + //Given + ArticleStore articleStore = new ArticleStore(); + UserStore userStore = new UserStore(); + var newUser = new User("Tom", "3@3.com"); + mock.Setup(repository => repository.CreateUser(newUser)) + .Returns(Task.FromResult(newUser)); + UserService userService = new UserService(articleStore, userStore, mock.Object); + + //When + User addedUser = await userService.CreateUserAsync(newUser); + + //Then + mock.Verify(repository => repository.CreateUser(newUser), Times.Once()); + } + + [Fact] + public void Should_return_user_when_invoke_GetByName_given_user_name() + { + //Given + var articleStore = new ArticleStore(); + var userStore = new UserStore(); + var userSertice = new UserService(articleStore, userStore, mock.Object); + + //Then + var getUser = userSertice.GetUser("Andrew"); + + //Then + mock.Verify(repository => repository.GetUser("Andrew"), Times.Once()); + } + + [Fact] + public void Should_return_all_user_when_invoke_GetAll() + { + //Given + var articleStore = new ArticleStore(); + var userStore = new UserStore(); + var userSertice = new UserService(articleStore, userStore, mock.Object); + + //Then + var users = userSertice.GetAllAsync(); + + //Then + mock.Verify(repository => repository.GetAllUsers(), Times.Once()); + } + + //[Fact] + //public void Should_return_updated_user_when_invoke_Update() + //{ + // //Given + // var articleStore = new ArticleStore(); + // var userStore = new UserStore(); + // var userService = new UserService(articleStore, userStore, mock.Object); + // var user = userService.GetByName("Andrew"); + // user.Email = "4@4.com"; + + // //Then + // var updatedUser = userService.Update(user); + + // //Then + // Assert.Equal("Andrew", updatedUser.Name); + // Assert.Equal(user.Email, updatedUser.Email); + //} + + //[Fact] + //public void Should_return_deleted_user_when_invoke_Delete() + //{ + // //Given + // var articleStore = new ArticleStore(); + // var userStore = new UserStore(); + // var userService = new UserService(articleStore, userStore, mock.Object); + // var userCountBeforeDelete = userService.GetAllAsync().Count(); + + // //Then + // var deletedUser = userService.Delete("Andrew"); + + // //Then + // Assert.Equal(userCountBeforeDelete - 1, userService.GetAllAsync().Count()); + // Assert.Equal("Andrew", deletedUser.Name); + //} + } +} diff --git a/MiniBlogTest/TestBase.cs b/MiniBlogTest/TestBase.cs index 02607cf..84d4706 100644 --- a/MiniBlogTest/TestBase.cs +++ b/MiniBlogTest/TestBase.cs @@ -18,7 +18,7 @@ public TestBase(CustomWebApplicationFactory factory) protected CustomWebApplicationFactory Factory { get; } - protected HttpClient GetClient(ArticleStore articleStore = null, UserStore userStore = null, IArticleRepository articleRepository = null) + protected HttpClient GetClient(ArticleStore articleStore = null, UserStore userStore = null, IArticleRepository articleRepository = null, IUserRepository userRepository = null) { return Factory.WithWebHostBuilder(builder => { @@ -34,12 +34,17 @@ protected HttpClient GetClient(ArticleStore articleStore = null, UserStore userS return userStore; }); services.AddScoped(); + services.AddScoped(); services.AddScoped(provider => { return articleRepository; }); + services.AddScoped(provider => + { + return userRepository; + }); }); }).CreateDefaultClient(); } } -} +} \ No newline at end of file