Skip to content

Commit b81a72c

Browse files
committed
Added Builder and Web tests
1 parent d1c1848 commit b81a72c

File tree

7 files changed

+171
-33
lines changed

7 files changed

+171
-33
lines changed

LinkDotNet.Blog.IntegrationTests/Infrastructure/Persistence/Sql/SqlRepositoryTests.cs

Lines changed: 9 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,21 @@
22
using System.Threading.Tasks;
33
using FluentAssertions;
44
using LinkDotNet.Domain;
5-
using LinkDotNet.Infrastructure.Persistence.Sql;
65
using Microsoft.EntityFrameworkCore;
76
using Xunit;
87

98
namespace LinkDotNet.Blog.IntegrationTests.Infrastructure.Persistence.Sql
109
{
11-
public sealed class SqlRepositoryTests : IAsyncLifetime
10+
public sealed class SqlRepositoryTests : SqlDatabaseTestBase
1211
{
13-
private readonly BlogPostRepository sut;
14-
private readonly BlogPostContext dbContext;
15-
16-
public SqlRepositoryTests()
17-
{
18-
var options = new DbContextOptionsBuilder()
19-
.UseSqlite("Data Source=IntegrationTest.db")
20-
.Options;
21-
dbContext = new BlogPostContext(options);
22-
sut = new BlogPostRepository(new BlogPostContext(options));
23-
}
24-
2512
[Fact]
2613
public async Task ShouldLoadBlogPost()
2714
{
2815
var blogPost = BlogPost.Create("Title", "Subtitle", "Content", "url", new[] { "Tag 1", "Tag 2" });
29-
await dbContext.BlogPosts.AddAsync(blogPost);
30-
await dbContext.SaveChangesAsync();
16+
await DbContext.BlogPosts.AddAsync(blogPost);
17+
await DbContext.SaveChangesAsync();
3118

32-
var blogPostFromRepo = await sut.GetByIdAsync(blogPost.Id);
19+
var blogPostFromRepo = await BlogPostRepository.GetByIdAsync(blogPost.Id);
3320

3421
blogPostFromRepo.Should().NotBeNull();
3522
blogPostFromRepo.Title.Should().Be("Title");
@@ -46,9 +33,9 @@ public async Task ShouldSaveBlogPost()
4633
{
4734
var blogPost = BlogPost.Create("Title", "Subtitle", "Content", "url", new[] { "Tag 1", "Tag 2" });
4835

49-
await sut.StoreAsync(blogPost);
36+
await BlogPostRepository.StoreAsync(blogPost);
5037

51-
var blogPostFromContext = await dbContext.BlogPosts.Include(b => b.Tags).AsNoTracking().SingleOrDefaultAsync(s => s.Id == blogPost.Id);
38+
var blogPostFromContext = await DbContext.BlogPosts.Include(b => b.Tags).AsNoTracking().SingleOrDefaultAsync(s => s.Id == blogPost.Id);
5239
blogPostFromContext.Should().NotBeNull();
5340
blogPostFromContext.Title.Should().Be("Title");
5441
blogPostFromContext.ShortDescription.Should().Be("Subtitle");
@@ -63,10 +50,10 @@ public async Task ShouldSaveBlogPost()
6350
public async Task ShouldGetAllBlogPosts()
6451
{
6552
var blogPost = BlogPost.Create("Title", "Subtitle", "Content", "url", new[] { "Tag 1", "Tag 2" });
66-
await dbContext.BlogPosts.AddAsync(blogPost);
67-
await dbContext.SaveChangesAsync();
53+
await DbContext.BlogPosts.AddAsync(blogPost);
54+
await DbContext.SaveChangesAsync();
6855

69-
var blogPostsFromRepo = (await sut.GetAllAsync()).ToList();
56+
var blogPostsFromRepo = (await BlogPostRepository.GetAllAsync()).ToList();
7057

7158
blogPostsFromRepo.Should().NotBeNull();
7259
blogPostsFromRepo.Should().HaveCount(1);
@@ -79,16 +66,5 @@ public async Task ShouldGetAllBlogPosts()
7966
var tagContent = blogPostFromRepo.Tags.Select(t => t.Content).ToList();
8067
tagContent.Should().Contain(new[] { "Tag 1", "Tag 2" });
8168
}
82-
83-
public Task InitializeAsync()
84-
{
85-
return Task.CompletedTask;
86-
}
87-
88-
async Task IAsyncLifetime.DisposeAsync()
89-
{
90-
await dbContext.Database.EnsureDeletedAsync();
91-
await dbContext.DisposeAsync();
92-
}
9369
}
9470
}

LinkDotNet.Blog.IntegrationTests/LinkDotNet.Blog.IntegrationTests.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10+
<PackageReference Include="bunit" Version="1.2.36-preview" />
1011
<PackageReference Include="FluentAssertions" Version="5.10.3" />
1112
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.7" />
1213
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
@@ -30,6 +31,8 @@
3031
</ItemGroup>
3132

3233
<ItemGroup>
34+
<ProjectReference Include="..\LinkDotNet.Blog.TestUtilities\LinkDotNet.Blog.TestUtilities.csproj" />
35+
<ProjectReference Include="..\LinkDotNet.Blog.Web\LinkDotNet.Blog.Web.csproj" />
3336
<ProjectReference Include="..\LinkDotNet.Infrastructure\LinkDotNet.Infrastructure.csproj" />
3437
</ItemGroup>
3538

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using LinkDotNet.Infrastructure.Persistence.Sql;
4+
using Microsoft.EntityFrameworkCore;
5+
using Xunit;
6+
7+
namespace LinkDotNet.Blog.IntegrationTests
8+
{
9+
public abstract class SqlDatabaseTestBase : IAsyncLifetime, IAsyncDisposable
10+
{
11+
protected BlogPostRepository BlogPostRepository { get; private set; }
12+
13+
protected BlogPostContext DbContext { get; private set; }
14+
15+
protected SqlDatabaseTestBase()
16+
{
17+
var options = new DbContextOptionsBuilder()
18+
.UseSqlite("Data Source=IntegrationTest.db")
19+
.Options;
20+
DbContext = new BlogPostContext(options);
21+
BlogPostRepository = new BlogPostRepository(new BlogPostContext(options));
22+
}
23+
24+
public Task InitializeAsync()
25+
{
26+
return Task.CompletedTask;
27+
}
28+
29+
async Task IAsyncLifetime.DisposeAsync()
30+
{
31+
await DisposeAsync();
32+
}
33+
34+
public async ValueTask DisposeAsync()
35+
{
36+
await DbContext.Database.EnsureDeletedAsync();
37+
await DbContext.DisposeAsync();
38+
}
39+
}
40+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System.Threading.Tasks;
2+
using Bunit;
3+
using FluentAssertions;
4+
using LinkDotNet.Blog.TestUtilities;
5+
using LinkDotNet.Blog.Web.Pages;
6+
using LinkDotNet.Infrastructure.Persistence;
7+
using Microsoft.Extensions.DependencyInjection;
8+
using Xunit;
9+
10+
namespace LinkDotNet.Blog.IntegrationTests.Web.Pages
11+
{
12+
public class SearchByTagTests : SqlDatabaseTestBase
13+
{
14+
[Fact]
15+
public async Task ShouldOnlyDisplayTagsGivenByParameter()
16+
{
17+
using var ctx = new TestContext();
18+
await AddBlogPostWithTagAsync("Tag 1");
19+
await AddBlogPostWithTagAsync("Tag 1");
20+
await AddBlogPostWithTagAsync("Tag 2");
21+
ctx.Services.AddScoped<IRepository>(_ => BlogPostRepository);
22+
var cut = ctx.RenderComponent<SearchByTag>(p => p.Add(s => s.Tag, "Tag 1"));
23+
24+
var tags = cut.FindAll(".blog-card");
25+
26+
tags.Should().HaveCount(2);
27+
}
28+
29+
private async Task AddBlogPostWithTagAsync(string tag)
30+
{
31+
var blogPost = new BlogPostBuilder().WithTags(tag).Build();
32+
await DbContext.AddAsync(blogPost);
33+
await DbContext.SaveChangesAsync();
34+
}
35+
}
36+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using LinkDotNet.Domain;
2+
3+
namespace LinkDotNet.Blog.TestUtilities
4+
{
5+
public class BlogPostBuilder
6+
{
7+
private string title = "BlogPost";
8+
private string shortDescription = "Some Text";
9+
private string content = "Some Content";
10+
private string url = "localhost";
11+
private string[] tags;
12+
13+
public BlogPostBuilder WithTitle(string title)
14+
{
15+
this.title = title;
16+
return this;
17+
}
18+
19+
public BlogPostBuilder WithShortDescription(string shortDescription)
20+
{
21+
this.shortDescription = shortDescription;
22+
return this;
23+
}
24+
25+
public BlogPostBuilder WithContent(string content)
26+
{
27+
this.content = content;
28+
return this;
29+
}
30+
31+
public BlogPostBuilder WithPreviewImageUrl(string url)
32+
{
33+
this.url = url;
34+
return this;
35+
}
36+
37+
public BlogPostBuilder WithTags(params string[] tags)
38+
{
39+
this.tags = tags;
40+
return this;
41+
}
42+
43+
public BlogPost Build()
44+
{
45+
return BlogPost.Create(title, shortDescription, content, url, tags);
46+
}
47+
}
48+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net5.0</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<PackageReference Include="SonarAnalyzer.CSharp" Version="8.25.0.33663">
9+
<PrivateAssets>all</PrivateAssets>
10+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
11+
</PackageReference>
12+
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.354">
13+
<PrivateAssets>all</PrivateAssets>
14+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
15+
</PackageReference>
16+
</ItemGroup>
17+
18+
<ItemGroup>
19+
<AdditionalFiles Include="..\stylecop.json" Link="stylecop.json" />
20+
</ItemGroup>
21+
22+
<ItemGroup>
23+
<ProjectReference Include="..\LinkDotNet.Domain\LinkDotNet.Domain.csproj" />
24+
</ItemGroup>
25+
<PropertyGroup>
26+
<CodeAnalysisRuleSet>..\stylecop.analyzers.ruleset</CodeAnalysisRuleSet>
27+
</PropertyGroup>
28+
29+
</Project>

LinkDotNet.Blog.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LinkDotNet.Blog.UnitTests",
1313
EndProject
1414
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LinkDotNet.Blog.IntegrationTests", "LinkDotNet.Blog.IntegrationTests\LinkDotNet.Blog.IntegrationTests.csproj", "{DEFDA17A-9586-4E50-83FB-8F75AC29D39A}"
1515
EndProject
16+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LinkDotNet.Blog.TestUtilities", "LinkDotNet.Blog.TestUtilities\LinkDotNet.Blog.TestUtilities.csproj", "{310ABEE1-C131-43E6-A759-F2DB75A483DD}"
17+
EndProject
1618
Global
1719
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1820
Debug|Any CPU = Debug|Any CPU
@@ -39,6 +41,10 @@ Global
3941
{DEFDA17A-9586-4E50-83FB-8F75AC29D39A}.Debug|Any CPU.Build.0 = Debug|Any CPU
4042
{DEFDA17A-9586-4E50-83FB-8F75AC29D39A}.Release|Any CPU.ActiveCfg = Release|Any CPU
4143
{DEFDA17A-9586-4E50-83FB-8F75AC29D39A}.Release|Any CPU.Build.0 = Release|Any CPU
44+
{310ABEE1-C131-43E6-A759-F2DB75A483DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
45+
{310ABEE1-C131-43E6-A759-F2DB75A483DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
46+
{310ABEE1-C131-43E6-A759-F2DB75A483DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
47+
{310ABEE1-C131-43E6-A759-F2DB75A483DD}.Release|Any CPU.Build.0 = Release|Any CPU
4248
EndGlobalSection
4349
GlobalSection(SolutionProperties) = preSolution
4450
HideSolutionNode = FALSE

0 commit comments

Comments
 (0)