Skip to content

Commit cc46769

Browse files
authored
Merge pull request #525 from aspnetboilerplate/maliming/web.test
Add Web.Tests project.
2 parents 33c6c09 + 0db4450 commit cc46769

File tree

6 files changed

+412
-0
lines changed

6 files changed

+412
-0
lines changed

aspnet-core/AbpCompanyName.AbpProjectName.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AbpCompanyName.AbpProjectNa
2323
EndProject
2424
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AbpCompanyName.AbpProjectName.EntityFrameworkCore", "src\AbpCompanyName.AbpProjectName.EntityFrameworkCore\AbpCompanyName.AbpProjectName.EntityFrameworkCore.csproj", "{E0580562-F8F2-4EBB-B07A-ABFC6F2C314F}"
2525
EndProject
26+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AbpCompanyName.AbpProjectName.Web.Tests", "test\AbpCompanyName.AbpProjectName.Web.Tests\AbpCompanyName.AbpProjectName.Web.Tests.csproj", "{CA86CF6F-5D9E-4DAC-9CCB-0F87B519E087}"
27+
EndProject
2628
Global
2729
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2830
Debug|Any CPU = Debug|Any CPU
@@ -61,6 +63,10 @@ Global
6163
{E0580562-F8F2-4EBB-B07A-ABFC6F2C314F}.Debug|Any CPU.Build.0 = Debug|Any CPU
6264
{E0580562-F8F2-4EBB-B07A-ABFC6F2C314F}.Release|Any CPU.ActiveCfg = Release|Any CPU
6365
{E0580562-F8F2-4EBB-B07A-ABFC6F2C314F}.Release|Any CPU.Build.0 = Release|Any CPU
66+
{CA86CF6F-5D9E-4DAC-9CCB-0F87B519E087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
67+
{CA86CF6F-5D9E-4DAC-9CCB-0F87B519E087}.Debug|Any CPU.Build.0 = Debug|Any CPU
68+
{CA86CF6F-5D9E-4DAC-9CCB-0F87B519E087}.Release|Any CPU.ActiveCfg = Release|Any CPU
69+
{CA86CF6F-5D9E-4DAC-9CCB-0F87B519E087}.Release|Any CPU.Build.0 = Release|Any CPU
6470
EndGlobalSection
6571
GlobalSection(SolutionProperties) = preSolution
6672
HideSolutionNode = FALSE
@@ -74,5 +80,6 @@ Global
7480
{22CFE0D2-8DCA-42D7-AD7D-784C3862493F} = {AFAA0841-BD93-466F-B8F4-FB4EEC86F1FC}
7581
{A2213374-BB48-48FD-BBD4-81E6A961D866} = {AFAA0841-BD93-466F-B8F4-FB4EEC86F1FC}
7682
{E0580562-F8F2-4EBB-B07A-ABFC6F2C314F} = {AFAA0841-BD93-466F-B8F4-FB4EEC86F1FC}
83+
{CA86CF6F-5D9E-4DAC-9CCB-0F87B519E087} = {F10AA149-2626-486E-85BB-9CD5365F3016}
7784
EndGlobalSection
7885
EndGlobal
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<VersionPrefix>1.0.0.0</VersionPrefix>
5+
<TargetFramework>netcoreapp3.1</TargetFramework>
6+
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
7+
<AssemblyName>AbpCompanyName.AbpProjectName.Web.Tests</AssemblyName>
8+
<PackageId>AbpCompanyName.AbpProjectName.Web.Tests</PackageId>
9+
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
10+
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
11+
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
12+
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
13+
</PropertyGroup>
14+
15+
<ItemGroup>
16+
<ProjectReference Include="..\..\src\AbpCompanyName.AbpProjectName.Web.Mvc\AbpCompanyName.AbpProjectName.Web.Mvc.csproj" />
17+
<ProjectReference Include="..\AbpCompanyName.AbpProjectName.Tests\AbpCompanyName.AbpProjectName.Tests.csproj" />
18+
</ItemGroup>
19+
20+
<ItemGroup>
21+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
22+
<PackageReference Include="NSubstitute" Version="4.2.1" />
23+
<PackageReference Include="Shouldly" Version="3.0.2" />
24+
<PackageReference Include="xunit" Version="2.4.1" />
25+
<PackageReference Include="xunit.extensibility.execution" Version="2.4.1" />
26+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
27+
<PrivateAssets>all</PrivateAssets>
28+
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
29+
</PackageReference>
30+
<PackageReference Include="Abp.AspNetCore.TestBase" Version="5.4.0" />
31+
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.1.0" />
32+
<PackageReference Include="Castle.Core" Version="4.4.0" />
33+
<PackageReference Include="AngleSharp" Version="0.13.0" />
34+
</ItemGroup>
35+
36+
</Project>
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
using System;
2+
using System.Linq;
3+
using System.Net;
4+
using System.Net.Http;
5+
using System.Net.Http.Headers;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
using Abp.AspNetCore.TestBase;
9+
using Abp.Authorization.Users;
10+
using Abp.Extensions;
11+
using Abp.Json;
12+
using Abp.MultiTenancy;
13+
using Abp.Web.Models;
14+
using AbpCompanyName.AbpProjectName.EntityFrameworkCore;
15+
using AbpCompanyName.AbpProjectName.Models.TokenAuth;
16+
using AbpCompanyName.AbpProjectName.Web.Startup;
17+
using AngleSharp.Html.Dom;
18+
using AngleSharp.Html.Parser;
19+
using Microsoft.AspNetCore.Hosting;
20+
using Newtonsoft.Json;
21+
using Newtonsoft.Json.Serialization;
22+
using Shouldly;
23+
24+
namespace AbpCompanyName.AbpProjectName.Web.Tests
25+
{
26+
public abstract class AbpProjectNameWebTestBase : AbpAspNetCoreIntegratedTestBase<Startup>
27+
{
28+
protected static readonly Lazy<string> ContentRootFolder;
29+
30+
static AbpProjectNameWebTestBase()
31+
{
32+
ContentRootFolder = new Lazy<string>(WebContentDirectoryFinder.CalculateContentRootFolder, true);
33+
}
34+
35+
protected override IWebHostBuilder CreateWebHostBuilder()
36+
{
37+
return base
38+
.CreateWebHostBuilder()
39+
.UseContentRoot(ContentRootFolder.Value)
40+
.UseSetting(WebHostDefaults.ApplicationKey, typeof(AbpProjectNameWebMvcModule).Assembly.FullName);
41+
}
42+
43+
#region Get response
44+
45+
protected async Task<T> GetResponseAsObjectAsync<T>(string url,
46+
HttpStatusCode expectedStatusCode = HttpStatusCode.OK)
47+
{
48+
var strResponse = await GetResponseAsStringAsync(url, expectedStatusCode);
49+
return JsonConvert.DeserializeObject<T>(strResponse, new JsonSerializerSettings
50+
{
51+
ContractResolver = new CamelCasePropertyNamesContractResolver()
52+
});
53+
}
54+
55+
protected async Task<string> GetResponseAsStringAsync(string url,
56+
HttpStatusCode expectedStatusCode = HttpStatusCode.OK)
57+
{
58+
var response = await GetResponseAsync(url, expectedStatusCode);
59+
return await response.Content.ReadAsStringAsync();
60+
}
61+
62+
protected async Task<HttpResponseMessage> GetResponseAsync(string url,
63+
HttpStatusCode expectedStatusCode = HttpStatusCode.OK)
64+
{
65+
var response = await Client.GetAsync(url);
66+
response.StatusCode.ShouldBe(expectedStatusCode);
67+
return response;
68+
}
69+
70+
#endregion
71+
72+
#region Authenticate
73+
74+
/// <summary>
75+
/// /api/TokenAuth/Authenticate
76+
/// TokenAuthController
77+
/// </summary>
78+
/// <param name="tenancyName"></param>
79+
/// <param name="input"></param>
80+
/// <returns></returns>
81+
protected async Task AuthenticateAsync(string tenancyName, AuthenticateModel input)
82+
{
83+
if (tenancyName.IsNullOrWhiteSpace())
84+
{
85+
var tenant = UsingDbContext(context => context.Tenants.FirstOrDefault(t => t.TenancyName == tenancyName));
86+
if (tenant != null)
87+
{
88+
AbpSession.TenantId = tenant.Id;
89+
Client.DefaultRequestHeaders.Add("Abp.TenantId", tenant.Id.ToString()); //Set TenantId
90+
}
91+
}
92+
93+
var response = await Client.PostAsync("/api/TokenAuth/Authenticate",
94+
new StringContent(input.ToJsonString(), Encoding.UTF8, "application/json"));
95+
response.StatusCode.ShouldBe(HttpStatusCode.OK);
96+
var result =
97+
JsonConvert.DeserializeObject<AjaxResponse<AuthenticateResultModel>>(
98+
await response.Content.ReadAsStringAsync());
99+
Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.Result.AccessToken);
100+
101+
AbpSession.UserId = result.Result.UserId;
102+
}
103+
104+
#endregion
105+
106+
#region Login
107+
108+
protected void LoginAsHostAdmin()
109+
{
110+
LoginAsHost(AbpUserBase.AdminUserName);
111+
}
112+
113+
protected void LoginAsDefaultTenantAdmin()
114+
{
115+
LoginAsTenant(AbpTenantBase.DefaultTenantName, AbpUserBase.AdminUserName);
116+
}
117+
118+
protected void LoginAsHost(string userName)
119+
{
120+
AbpSession.TenantId = null;
121+
122+
var user =
123+
UsingDbContext(
124+
context =>
125+
context.Users.FirstOrDefault(u => u.TenantId == AbpSession.TenantId && u.UserName == userName));
126+
if (user == null)
127+
{
128+
throw new Exception("There is no user: " + userName + " for host.");
129+
}
130+
131+
AbpSession.UserId = user.Id;
132+
}
133+
134+
protected void LoginAsTenant(string tenancyName, string userName)
135+
{
136+
var tenant = UsingDbContext(context => context.Tenants.FirstOrDefault(t => t.TenancyName == tenancyName));
137+
if (tenant == null)
138+
{
139+
throw new Exception("There is no tenant: " + tenancyName);
140+
}
141+
142+
AbpSession.TenantId = tenant.Id;
143+
144+
var user =
145+
UsingDbContext(
146+
context =>
147+
context.Users.FirstOrDefault(u => u.TenantId == AbpSession.TenantId && u.UserName == userName));
148+
if (user == null)
149+
{
150+
throw new Exception("There is no user: " + userName + " for tenant: " + tenancyName);
151+
}
152+
153+
AbpSession.UserId = user.Id;
154+
}
155+
156+
#endregion
157+
158+
159+
#region UsingDbContext
160+
161+
protected void UsingDbContext(Action<AbpProjectNameDbContext> action)
162+
{
163+
using (var context = IocManager.Resolve<AbpProjectNameDbContext>())
164+
{
165+
action(context);
166+
context.SaveChanges();
167+
}
168+
}
169+
170+
protected T UsingDbContext<T>(Func<AbpProjectNameDbContext, T> func)
171+
{
172+
T result;
173+
174+
using (var context = IocManager.Resolve<AbpProjectNameDbContext>())
175+
{
176+
result = func(context);
177+
context.SaveChanges();
178+
}
179+
180+
return result;
181+
}
182+
183+
protected async Task UsingDbContextAsync(Func<AbpProjectNameDbContext, Task> action)
184+
{
185+
using (var context = IocManager.Resolve<AbpProjectNameDbContext>())
186+
{
187+
await action(context);
188+
await context.SaveChangesAsync(true);
189+
}
190+
}
191+
192+
protected async Task<T> UsingDbContextAsync<T>(Func<AbpProjectNameDbContext, Task<T>> func)
193+
{
194+
T result;
195+
196+
using (var context = IocManager.Resolve<AbpProjectNameDbContext>())
197+
{
198+
result = await func(context);
199+
await context.SaveChangesAsync(true);
200+
}
201+
202+
return result;
203+
}
204+
205+
#endregion
206+
207+
#region ParseHtml
208+
209+
protected IHtmlDocument ParseHtml(string htmlString)
210+
{
211+
return new HtmlParser().ParseDocument(htmlString);
212+
}
213+
214+
#endregion
215+
}
216+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using Abp.AspNetCore;
2+
using Abp.AspNetCore.TestBase;
3+
using Abp.Modules;
4+
using Abp.Reflection.Extensions;
5+
using AbpCompanyName.AbpProjectName.EntityFrameworkCore;
6+
using AbpCompanyName.AbpProjectName.Web.Startup;
7+
using Microsoft.AspNetCore.Mvc.ApplicationParts;
8+
9+
namespace AbpCompanyName.AbpProjectName.Web.Tests
10+
{
11+
[DependsOn(
12+
typeof(AbpProjectNameWebMvcModule),
13+
typeof(AbpAspNetCoreTestBaseModule)
14+
)]
15+
public class AbpProjectNameWebTestModule : AbpModule
16+
{
17+
public AbpProjectNameWebTestModule(AbpProjectNameEntityFrameworkModule abpProjectNameEntityFrameworkModule)
18+
{
19+
abpProjectNameEntityFrameworkModule.SkipDbContextRegistration = true;
20+
}
21+
22+
public override void PreInitialize()
23+
{
24+
Configuration.UnitOfWork.IsTransactional = false; //EF Core InMemory DB does not support transactions.
25+
}
26+
27+
public override void Initialize()
28+
{
29+
IocManager.RegisterAssemblyByConvention(typeof(AbpProjectNameWebTestModule).GetAssembly());
30+
}
31+
32+
public override void PostInitialize()
33+
{
34+
IocManager.Resolve<ApplicationPartManager>()
35+
.AddApplicationPartsIfNotAddedBefore(typeof(AbpProjectNameWebMvcModule).Assembly);
36+
}
37+
}
38+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System.Threading.Tasks;
2+
using AbpCompanyName.AbpProjectName.Models.TokenAuth;
3+
using AbpCompanyName.AbpProjectName.Web.Controllers;
4+
using Shouldly;
5+
using Xunit;
6+
7+
namespace AbpCompanyName.AbpProjectName.Web.Tests.Controllers
8+
{
9+
public class HomeController_Tests: AbpProjectNameWebTestBase
10+
{
11+
[Fact]
12+
public async Task Index_Test()
13+
{
14+
await AuthenticateAsync(null, new AuthenticateModel
15+
{
16+
UserNameOrEmailAddress = "admin",
17+
Password = "123qwe"
18+
});
19+
20+
//Act
21+
var response = await GetResponseAsStringAsync(
22+
GetUrl<HomeController>(nameof(HomeController.Index))
23+
);
24+
25+
//Assert
26+
response.ShouldNotBeNullOrEmpty();
27+
}
28+
}
29+
}

0 commit comments

Comments
 (0)