From b6f26f9e7d0352d37cb5c11897bf25ff7f0b2a56 Mon Sep 17 00:00:00 2001 From: dudu Date: Thu, 20 Sep 2018 14:30:42 +0800 Subject: [PATCH] Rewrite SampleWebApp and add integration tests --- .../MemcachedClientTestsBase.cs | 2 +- Enyim.Caching/MemcachedClient.cs | 4 ++ EnyimCachingCore.sln | 10 ++++ .../HomeControllerTests.cs | 41 ++++++++++++++ .../Properties/launchSettings.json | 27 +++++++++ .../SampleWebApp.IntegrationTests.csproj | 25 +++++++++ SampleWebApp/Controllers/HomeController.cs | 45 +++++++++++++++ SampleWebApp/Models/BlogPost.cs | 13 +++++ SampleWebApp/Program.cs | 15 ++--- SampleWebApp/SampleWebApp.csproj | 2 + SampleWebApp/Services/BlogPostService.cs | 16 ++++++ SampleWebApp/Services/IBlogPostService.cs | 13 +++++ SampleWebApp/Startup.cs | 56 ++++--------------- test.sh | 5 +- 14 files changed, 218 insertions(+), 56 deletions(-) create mode 100644 SampleWebApp.IntegrationTests/HomeControllerTests.cs create mode 100644 SampleWebApp.IntegrationTests/Properties/launchSettings.json create mode 100644 SampleWebApp.IntegrationTests/SampleWebApp.IntegrationTests.csproj create mode 100644 SampleWebApp/Controllers/HomeController.cs create mode 100644 SampleWebApp/Models/BlogPost.cs create mode 100644 SampleWebApp/Services/BlogPostService.cs create mode 100644 SampleWebApp/Services/IBlogPostService.cs diff --git a/Enyim.Caching.Tests/MemcachedClientTestsBase.cs b/Enyim.Caching.Tests/MemcachedClientTestsBase.cs index c2615bcf..c05beeef 100644 --- a/Enyim.Caching.Tests/MemcachedClientTestsBase.cs +++ b/Enyim.Caching.Tests/MemcachedClientTestsBase.cs @@ -26,7 +26,7 @@ public MemcachedClientTestsBase(Action onAddEnyimMemcach onAddEnyimMemcached?.Invoke(options); }); - services.AddLogging(builder => builder.SetMinimumLevel(LogLevel.Debug).AddConsole()); + services.AddLogging(builder => builder.SetMinimumLevel(LogLevel.Information).AddConsole()); IServiceProvider serviceProvider = services.BuildServiceProvider(); _client = serviceProvider.GetService() as MemcachedClient; } diff --git a/Enyim.Caching/MemcachedClient.cs b/Enyim.Caching/MemcachedClient.cs index fc7a6cd5..58ce2495 100755 --- a/Enyim.Caching/MemcachedClient.cs +++ b/Enyim.Caching/MemcachedClient.cs @@ -220,6 +220,7 @@ public async Task GetValueOrCreateAsync(string key, int cacheSeconds, Func var result = await GetAsync(key); if (result.Success) { + _logger.LogDebug($"Cache is hint. Key is '{key}'."); return result.Value; } } @@ -228,12 +229,15 @@ public async Task GetValueOrCreateAsync(string key, int cacheSeconds, Func _logger.LogError(ex, $"{nameof(GetAsync)}<{typeof(T)}>(\"{key}\")"); } + _logger.LogDebug($"Cache is missed. Key is '{key}'."); + var value = await generator?.Invoke(); if (value != null) { try { await AddAsync(key, value, cacheSeconds); + _logger.LogDebug($"Added value into cache. Key is '{key}'. " + value); } catch (Exception ex) { diff --git a/EnyimCachingCore.sln b/EnyimCachingCore.sln index 61434ca6..94c6f1d7 100644 --- a/EnyimCachingCore.sln +++ b/EnyimCachingCore.sln @@ -17,6 +17,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{46CD2BBA-9 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{9954C92E-50E2-477C-AC47-31C857C46370}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleWebApp.IntegrationTests", "SampleWebApp.IntegrationTests\SampleWebApp.IntegrationTests.csproj", "{281CA49A-FEA5-4008-8D3D-0C4E1C548B8C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -39,6 +41,10 @@ Global {3DDAC26F-8B56-4F69-8C69-A3CB6CF6B12B}.Debug|Any CPU.Build.0 = Debug|Any CPU {3DDAC26F-8B56-4F69-8C69-A3CB6CF6B12B}.Release|Any CPU.ActiveCfg = Release|Any CPU {3DDAC26F-8B56-4F69-8C69-A3CB6CF6B12B}.Release|Any CPU.Build.0 = Release|Any CPU + {281CA49A-FEA5-4008-8D3D-0C4E1C548B8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {281CA49A-FEA5-4008-8D3D-0C4E1C548B8C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {281CA49A-FEA5-4008-8D3D-0C4E1C548B8C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {281CA49A-FEA5-4008-8D3D-0C4E1C548B8C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -48,5 +54,9 @@ Global {7F795CB9-6058-4137-B069-12C1B8D4132B} = {9954C92E-50E2-477C-AC47-31C857C46370} {FAF5E655-9ED4-4934-94F9-F0EDB77143AC} = {46CD2BBA-9846-42FA-823B-D03F68F81647} {3DDAC26F-8B56-4F69-8C69-A3CB6CF6B12B} = {46CD2BBA-9846-42FA-823B-D03F68F81647} + {281CA49A-FEA5-4008-8D3D-0C4E1C548B8C} = {9954C92E-50E2-477C-AC47-31C857C46370} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D8C07FE8-52FF-48B8-A079-A180058AABC6} EndGlobalSection EndGlobal diff --git a/SampleWebApp.IntegrationTests/HomeControllerTests.cs b/SampleWebApp.IntegrationTests/HomeControllerTests.cs new file mode 100644 index 00000000..d343ed67 --- /dev/null +++ b/SampleWebApp.IntegrationTests/HomeControllerTests.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using Enyim.Caching; +using Enyim.Caching.SampleWebApp; +using Enyim.Caching.SampleWebApp.Controllers; +using Enyim.Caching.SampleWebApp.Models; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace SampleWebApp.IntegrationTests +{ + public class HomeControllerTests : IClassFixture> + { + private readonly WebApplicationFactory _factory; + + public HomeControllerTests(WebApplicationFactory factory) + { + _factory = factory; + } + + [Fact] + public async Task HomeController_Index() + { + var httpClient = _factory.CreateClient(); + var response = await httpClient.GetAsync("/"); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + var memcachedClient = _factory.Server.Host.Services.GetRequiredService(); + var posts = await memcachedClient.GetValueAsync>(HomeController.CacheKey); + Assert.NotNull(posts); + Assert.NotEmpty(posts.First().Title); + + await memcachedClient.RemoveAsync(HomeController.CacheKey); + } + } +} diff --git a/SampleWebApp.IntegrationTests/Properties/launchSettings.json b/SampleWebApp.IntegrationTests/Properties/launchSettings.json new file mode 100644 index 00000000..229529d6 --- /dev/null +++ b/SampleWebApp.IntegrationTests/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:57329/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "SampleWebApp.IntegrationTests": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:57330/" + } + } +} \ No newline at end of file diff --git a/SampleWebApp.IntegrationTests/SampleWebApp.IntegrationTests.csproj b/SampleWebApp.IntegrationTests/SampleWebApp.IntegrationTests.csproj new file mode 100644 index 00000000..26600ca3 --- /dev/null +++ b/SampleWebApp.IntegrationTests/SampleWebApp.IntegrationTests.csproj @@ -0,0 +1,25 @@ + + + + netcoreapp2.1 + + false + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + + + diff --git a/SampleWebApp/Controllers/HomeController.cs b/SampleWebApp/Controllers/HomeController.cs new file mode 100644 index 00000000..961f17ed --- /dev/null +++ b/SampleWebApp/Controllers/HomeController.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Enyim.Caching; +using Enyim.Caching.SampleWebApp.Models; +using Enyim.Caching.SampleWebApp.Services; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; + +namespace Enyim.Caching.SampleWebApp.Controllers +{ + public class HomeController : Controller + { + private readonly IMemcachedClient _memcachedClient; + private readonly IBlogPostService _blogPostService; + private readonly ILogger _logger; + public static readonly string CacheKey = "blogposts-recent"; + + public HomeController( + IMemcachedClient memcachedClient, + IBlogPostService blogPostService, + ILoggerFactory loggerFactory) + { + _memcachedClient = memcachedClient; + _blogPostService = blogPostService; + _logger = loggerFactory.CreateLogger(); + } + + public async Task Index() + { + _logger.LogDebug("Executing _memcachedClient.GetValueOrCreateAsync..."); + + var cacheSeconds = 600; + var posts = await _memcachedClient.GetValueOrCreateAsync( + CacheKey, + cacheSeconds, + async () => await _blogPostService.GetRecent(10)); + + _logger.LogDebug("Done _memcachedClient.GetValueOrCreateAsync"); + + return Ok(posts); + } + } +} diff --git a/SampleWebApp/Models/BlogPost.cs b/SampleWebApp/Models/BlogPost.cs new file mode 100644 index 00000000..625299ac --- /dev/null +++ b/SampleWebApp/Models/BlogPost.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Enyim.Caching.SampleWebApp.Models +{ + public class BlogPost + { + public string Title { get; set; } + public string Body { get; set; } + } +} diff --git a/SampleWebApp/Program.cs b/SampleWebApp/Program.cs index 88238ae6..98f31c16 100644 --- a/SampleWebApp/Program.cs +++ b/SampleWebApp/Program.cs @@ -3,23 +3,20 @@ using System.IO; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; -namespace SampleWebApp +namespace Enyim.Caching.SampleWebApp { public class Program { public static void Main(string[] args) { - BuildWebHost(args).Run(); + CreateWebHostBuilder(args).Build().Run(); } - public static IWebHost BuildWebHost(string[] args) - { - return WebHost.CreateDefaultBuilder(args) - .UseStartup() - .Build(); - } + public static IWebHostBuilder CreateWebHostBuilder(string[] args) => + WebHost.CreateDefaultBuilder(args) + .UseStartup(); } } diff --git a/SampleWebApp/SampleWebApp.csproj b/SampleWebApp/SampleWebApp.csproj index 9c269579..6c426750 100644 --- a/SampleWebApp/SampleWebApp.csproj +++ b/SampleWebApp/SampleWebApp.csproj @@ -2,6 +2,8 @@ netcoreapp2.1 + Enyim.Caching.SampleWebApp + Enyim.Caching.SampleWebApp diff --git a/SampleWebApp/Services/BlogPostService.cs b/SampleWebApp/Services/BlogPostService.cs new file mode 100644 index 00000000..98666398 --- /dev/null +++ b/SampleWebApp/Services/BlogPostService.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Enyim.Caching.SampleWebApp.Models; + +namespace Enyim.Caching.SampleWebApp.Services +{ + public class BlogPostService : IBlogPostService + { + public async ValueTask> GetRecent(int itemCount) + { + return new List { new BlogPost { Title = "Hello World", Body = "EnyimCachingCore" } }; + } + } +} diff --git a/SampleWebApp/Services/IBlogPostService.cs b/SampleWebApp/Services/IBlogPostService.cs new file mode 100644 index 00000000..dc2b1619 --- /dev/null +++ b/SampleWebApp/Services/IBlogPostService.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Enyim.Caching.SampleWebApp.Models; + +namespace Enyim.Caching.SampleWebApp.Services +{ + public interface IBlogPostService + { + ValueTask> GetRecent(int itemCount); + } +} diff --git a/SampleWebApp/Startup.cs b/SampleWebApp/Startup.cs index d262ba29..2dab5d4c 100644 --- a/SampleWebApp/Startup.cs +++ b/SampleWebApp/Startup.cs @@ -2,33 +2,26 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Enyim.Caching; +using Enyim.Caching.SampleWebApp.Services; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Caching.Distributed; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using Enyim.Caching; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Caching.Distributed; -namespace SampleWebApp +namespace Enyim.Caching.SampleWebApp { public class Startup { - public Startup(IHostingEnvironment env) + public Startup(IConfiguration configuration) { - var builder = new ConfigurationBuilder() - .SetBasePath(env.ContentRootPath) - .AddJsonFile("appsettings.json") - .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) - .AddEnvironmentVariables(); - Configuration = builder.Build(); - IsDevelopment = env.IsDevelopment(); + Configuration = configuration; } - public IConfigurationRoot Configuration { get; set; } - - public bool IsDevelopment { get; set; } + public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { @@ -36,39 +29,14 @@ public void ConfigureServices(IServiceCollection services) //services.AddEnyimMemcached(Configuration); //services.AddEnyimMemcached(Configuration, "enyimMemcached"); //services.AddEnyimMemcached(Configuration.GetSection("enyimMemcached")); + services.AddTransient(); + services.AddMvc(); } - public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + public void Configure(IApplicationBuilder app) { app.UseEnyimMemcached(); - - var memcachedClient = app.ApplicationServices.GetService(); - var distributedCache = app.ApplicationServices.GetService(); - var logger = loggerFactory.CreateLogger(); - - app.Run(async (context) => - { - var cacheKey = "sample_response"; - var distributedCaceKey = "distributed_" + cacheKey; - await memcachedClient.AddAsync(cacheKey, $"Hello World from {nameof(memcachedClient)}!", 60); - await distributedCache.SetStringAsync(distributedCaceKey,$"Hello World from {nameof(distributedCache)}!"); - var cacheResult = await memcachedClient.GetAsync(cacheKey); - if (cacheResult.Success) - { - var distributedCacheValue = await distributedCache.GetStringAsync(distributedCaceKey); - await context.Response - .WriteAsync($"memcachedClient: {cacheResult.Value}\ndistributedCache: {distributedCacheValue}"); - await memcachedClient.RemoveAsync(cacheKey); - await distributedCache.RemoveAsync(distributedCaceKey); - logger.LogDebug($"Hinted cache with '{cacheKey}' key"); - } - else - { - var message = $"Missed cache with '{cacheKey}' key"; - await context.Response.WriteAsync(message); - logger.LogError(message); - } - }); + app.UseMvcWithDefaultRoute(); } } } diff --git a/test.sh b/test.sh index 81779d93..d23a5c18 100755 --- a/test.sh +++ b/test.sh @@ -1,3 +1,4 @@ #!/usr/bin/env bash -dotnet test Enyim.Caching.Tests/Enyim.Caching.Tests.csproj -c Release -v normal -dotnet test MemcachedTest/MemcachedTest.csproj -c Release -v normal +dotnet test SampleWebApp.IntegrationTests/*.csproj -c Release +dotnet test Enyim.Caching.Tests/*.csproj -c Release +dotnet test MemcachedTest/*.csproj -c Release