From b0c5d2b08b8d649e41e2930c5927ac605813fdf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Mon, 3 Jun 2019 15:13:05 +0300 Subject: [PATCH] Update mvc tutorial --- docs/en/Tutorials/AspNetCore-Mvc/Part-I.md | 2 +- docs/en/Tutorials/AspNetCore-Mvc/Part-III.md | 87 ++++++------------ .../images/bookstore-appservice-tests.png | Bin 0 -> 16291 bytes .../images/bookstore-test-projects-v2.png | Bin 0 -> 6864 bytes .../images/bookstore-test-projects.png | Bin 7399 -> 0 bytes 5 files changed, 28 insertions(+), 61 deletions(-) create mode 100644 docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-appservice-tests.png create mode 100644 docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects-v2.png delete mode 100644 docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects.png diff --git a/docs/en/Tutorials/AspNetCore-Mvc/Part-I.md b/docs/en/Tutorials/AspNetCore-Mvc/Part-I.md index afc4e6515b..288f7fe075 100644 --- a/docs/en/Tutorials/AspNetCore-Mvc/Part-I.md +++ b/docs/en/Tutorials/AspNetCore-Mvc/Part-I.md @@ -4,7 +4,7 @@ In this tutorial series, you will build an application that is used to manage a list of books & their authors. **Entity Framework Core** (EF Core) will be used as the ORM provider as it is the default database provider. -This is the first part of the tutorial series. See all parts: +This is the first part of the ASP.NET Core MVC tutorial series. See all parts: - **Part I: Create the project and a book list page (this tutorial)** - [Part II: Create, Update and Delete books](Part-II.md) diff --git a/docs/en/Tutorials/AspNetCore-Mvc/Part-III.md b/docs/en/Tutorials/AspNetCore-Mvc/Part-III.md index b70521dad0..ad632c2366 100644 --- a/docs/en/Tutorials/AspNetCore-Mvc/Part-III.md +++ b/docs/en/Tutorials/AspNetCore-Mvc/Part-III.md @@ -2,22 +2,21 @@ ### About this Tutorial -This is the third part of the tutorial series. See all parts: +This is the third part of the ASP.NET Core MVC tutorial series. See all parts: - [Part I: Create the project and a book list page](Part-I.md) - [Part II: Create, Update and Delete books](Part-II.md) - **Part III: Integration Tests (this tutorial)** -You can download the **source code** of the application [from here](https://github.com/volosoft/abp/tree/master/samples/BookStore). +You can access to the **source code** of the application from [the GitHub repository](https://github.com/volosoft/abp/tree/master/samples/BookStore). ### Test Projects in the Solution -There are two test projects in the solution: +There are multiple test projects in the solution: -* `Acme.BookStore.Application.Tests` is for unit & integration tests. You can write tests for application service methods. It uses **EF Core SQLite in-memory** database. -* `Acme.BookStore.Web.Tests` is for full stack integration tests including the web layer. So, you can write tests for UI pages too. +![bookstore-test-projects-v2](images/bookstore-test-projects-v2.png) -Test projects use the following libraries for testing: +Each project is used to test the related application project. Test projects use the following libraries for testing: * [xunit](https://xunit.github.io/) as the main test framework. * [Shoudly](http://shouldly.readthedocs.io/en/latest/) as an assertion library. @@ -25,79 +24,40 @@ Test projects use the following libraries for testing: ### Adding Test Data -Startup template contains the `BookStoreTestDataBuilder` class in the `Acme.BookStore.Application.Tests` project that creates some data to run tests on. It's shown below: +Startup template contains the `BookStoreTestDataSeedContributor` class in the `Acme.BookStore.TestBase` project that creates some data to run tests on. -````C# -using System.Threading.Tasks; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Identity; -using Volo.Abp.Threading; - -namespace Acme.BookStore -{ - public class BookStoreTestDataBuilder : ITransientDependency - { - private readonly IIdentityDataSeeder _identityDataSeeder; - - public BookStoreTestDataBuilder(IIdentityDataSeeder identityDataSeeder) - { - _identityDataSeeder = identityDataSeeder; - } - - public void Build() - { - AsyncHelper.RunSync(BuildInternalAsync); - } - - public async Task BuildInternalAsync() - { - await _identityDataSeeder.SeedAsync("1q2w3E*"); - } - } -} -```` - -* It simply uses `IIdentityDataSeeder` which is implemented by the identity module and creates an admin role and admin user. You can use them in your tests. -* You can add new test data in the `BuildInternalAsync` method. - -Change the `BookStoreTestDataBuilder` class as show below: +Change the `BookStoreTestDataSeedContributor` class as show below: ````C# using System; using System.Threading.Tasks; +using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Repositories; -using Volo.Abp.Identity; -using Volo.Abp.Threading; +using Volo.Abp.Guids; namespace Acme.BookStore { - public class BookStoreTestDataBuilder : ITransientDependency + public class BookStoreTestDataSeedContributor + : IDataSeedContributor, ITransientDependency { - private readonly IIdentityDataSeeder _identityDataSeeder; private readonly IRepository _bookRepository; + private readonly IGuidGenerator _guidGenerator; - public BookStoreTestDataBuilder( - IIdentityDataSeeder identityDataSeeder, - IRepository bookRepository) + public BookStoreTestDataSeedContributor( + IRepository bookRepository, + IGuidGenerator guidGenerator) { - _identityDataSeeder = identityDataSeeder; _bookRepository = bookRepository; + _guidGenerator = guidGenerator; } - public void Build() + public async Task SeedAsync(DataSeedContext context) { - AsyncHelper.RunSync(BuildInternalAsync); - } - - public async Task BuildInternalAsync() - { - await _identityDataSeeder.SeedAsync("1q2w3E*"); - await _bookRepository.InsertAsync( new Book { - Id = Guid.NewGuid(), + Id = _guidGenerator.Create(), Name = "Test book 1", Type = BookType.Fantastic, PublishDate = new DateTime(2015, 05, 24), @@ -108,7 +68,7 @@ namespace Acme.BookStore await _bookRepository.InsertAsync( new Book { - Id = Guid.NewGuid(), + Id = _guidGenerator.Create(), Name = "Test book 2", Type = BookType.Science, PublishDate = new DateTime(2014, 02, 11), @@ -120,7 +80,8 @@ namespace Acme.BookStore } ```` -* Injected `IRepository` and used it in the `BuildInternalAsync` to create two book entities. +* Injected `IRepository` and used it in the `SeedAsync` to create two book entities as the test data. +* Used `IGuidGenerator` service to create GUIDs. While `Guid.NewGuid()` would perfectly work for testing, `IGuidGenerator` has additional features especially important while using real databases (see the [Guid generation document](../../Guid-Generation.md) for more). ### Testing the BookAppService @@ -210,6 +171,12 @@ public async Task Should_Not_Create_A_Book_Without_Name() * Since the `Name` is empty, ABP throws an `AbpValidationException`. +Open the **Test Explorer Window** (use Test -> Windows -> Test Explorer menu if it is not visible) and **Run All** tests: + +![bookstore-appservice-tests](images/bookstore-appservice-tests.png) + +Congratulations, green icons show that tests have been successfully passed! + ### Testing Web Pages TODO \ No newline at end of file diff --git a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-appservice-tests.png b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-appservice-tests.png new file mode 100644 index 0000000000000000000000000000000000000000..942d2832a62db6a9cc581569c1685d34939b8e2b GIT binary patch literal 16291 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 literal 0 HcmV?d00001 diff --git a/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects-v2.png b/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects-v2.png new file mode 100644 index 0000000000000000000000000000000000000000..8701164d7514d15b27b6f83dfde1536bc38f5c58 GIT binary patch literal 6864 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