Skip to content
This repository was archived by the owner on Apr 20, 2024. It is now read-only.

Commit 691a19e

Browse files
author
Morten Turn Pedersen
authored
Merge pull request #6 from nodes-dotnet/feature/unit-tests
Feature/unit tests
2 parents c3fedd4 + 84f8847 commit 691a19e

File tree

12 files changed

+375
-9
lines changed

12 files changed

+375
-9
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
parameters:
2+
- name: projects
3+
type: string
4+
default: '**/*[Tt]ests/*.csproj'
5+
6+
- name: buildConfiguration
7+
type: string
8+
default: 'Release'
9+
10+
steps:
11+
- task: DotNetCoreCLI@2
12+
displayName: 'Run unit tests'
13+
inputs:
14+
command: 'test'
15+
projects: '${{parameters.projects}}'
16+
arguments: '--configuration ${{parameters.buildConfiguration}}'

Build Configurations/ci.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,6 @@ steps:
2222
projects: '**/NetCoreEntityFramework.csproj'
2323
buildConfiguration: '$(buildConfiguration)'
2424
skipBuild: true
25-
skipInstall: true
25+
skipInstall: true
26+
27+
- template: 'Templates/Test Net Core.yml'
Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
using AutoFixture.NUnit3;
2+
using Microsoft.EntityFrameworkCore;
3+
using Nodes.NetCore.EntityFramework.Tests.Mocks;
4+
using NUnit.Framework;
5+
using System;
6+
using System.Threading.Tasks;
7+
using TestContext = Nodes.NetCore.EntityFramework.Tests.Mocks.TestContext;
8+
9+
namespace Nodes.NetCore.EntityFramework.Tests
10+
{
11+
public class EntityRepositoryTests
12+
{
13+
private TestEntityRepository _repository;
14+
private TestContext _context;
15+
private TestEntity _entity;
16+
private TestEntity _deletedEntity;
17+
18+
[SetUp]
19+
public void Setup()
20+
{
21+
var options = new DbContextOptionsBuilder<TestContext>()
22+
.UseInMemoryDatabase(Guid.NewGuid().ToString())
23+
.Options;
24+
25+
_context = new TestContext(options);
26+
27+
_repository = new TestEntityRepository(_context);
28+
29+
DateTime now = DateTime.UtcNow;
30+
31+
_entity = new TestEntity
32+
{
33+
Created = now,
34+
Deleted = false,
35+
Id = Guid.NewGuid(),
36+
Updated = now,
37+
Property = string.Empty
38+
};
39+
40+
_deletedEntity = new TestEntity
41+
{
42+
Created = now.AddMinutes(-42),
43+
Deleted = true,
44+
DeletedAt = now,
45+
Id = Guid.NewGuid(),
46+
Updated = now.AddMinutes(-42),
47+
Property = "I'm deleted"
48+
};
49+
50+
_context.Table.Add(_entity);
51+
_context.Table.Add(_deletedEntity);
52+
53+
_context.SaveChanges();
54+
55+
_repository = new TestEntityRepository(_context);
56+
}
57+
58+
#region Add
59+
[Test]
60+
public async Task AddAddsEntityAndSetsAttributes()
61+
{
62+
int startSize = await _context.Table.CountAsync();
63+
int expectedSize = startSize + 1;
64+
var entity = new TestEntity();
65+
66+
using(_repository)
67+
{
68+
await _repository.Add(entity);
69+
}
70+
71+
Assert.NotNull(entity.Id);
72+
Assert.AreNotEqual(default(DateTime), entity.Created);
73+
Assert.AreNotEqual(default(DateTime), entity.Updated);
74+
Assert.IsFalse(entity.Deleted);
75+
Assert.AreEqual(expectedSize, await _context.Table.CountAsync());
76+
}
77+
78+
[Test]
79+
public async Task AddEntityWithIdKeepsId()
80+
{
81+
Guid id = Guid.NewGuid();
82+
var entity = new TestEntity
83+
{
84+
Id = id
85+
};
86+
87+
using (_repository)
88+
{
89+
await _repository.Add(entity);
90+
}
91+
92+
Assert.AreEqual(id, entity.Id);
93+
}
94+
95+
[Test]
96+
public void AddThrowsExceptionIfEntityIsNull()
97+
{
98+
Assert.ThrowsAsync<ArgumentNullException>(() => _repository.Add(null));
99+
}
100+
#endregion
101+
102+
#region Get
103+
[Test]
104+
public async Task GetValidEntityReturnsEntity()
105+
{
106+
var entity = await _repository.Get((Guid)_entity.Id);
107+
108+
Assert.AreSame(_entity, entity);
109+
}
110+
111+
[Test]
112+
public async Task DontGetDeletedEntityWithoutFlag()
113+
{
114+
var entity = await _repository.Get((Guid)_deletedEntity.Id);
115+
116+
Assert.IsNull(entity);
117+
}
118+
119+
[Test]
120+
public async Task GetDeletedEntityWithFlag()
121+
{
122+
var entity = await _repository.Get((Guid)_deletedEntity.Id, true);
123+
124+
Assert.AreSame(_deletedEntity, entity);
125+
}
126+
#endregion
127+
128+
#region Update
129+
[Test]
130+
[AutoData]
131+
public async Task UpdateUpdatesUpdated(string propertyValue)
132+
{
133+
DateTime oldUpdated = _entity.Updated;
134+
DateTime oldCreated = _entity.Created;
135+
_entity.Property = propertyValue;
136+
137+
using(_repository)
138+
{
139+
await _repository.Update(_entity);
140+
}
141+
142+
var entity = await _repository.Get((Guid)_entity.Id);
143+
144+
Assert.AreEqual(propertyValue, entity.Property);
145+
Assert.AreNotEqual(oldUpdated, entity.Updated);
146+
Assert.AreEqual(oldCreated, entity.Created);
147+
}
148+
149+
[Test]
150+
public void UpdateThrowsExceptionIfNull()
151+
{
152+
Assert.ThrowsAsync<ArgumentNullException>(() => _repository.Update(null));
153+
}
154+
#endregion
155+
156+
#region Delete
157+
[Test]
158+
public async Task DeleteSoftDeletesAndSetsDeletedAt()
159+
{
160+
bool success;
161+
using(_repository)
162+
{
163+
success = await _repository.Delete(_entity);
164+
}
165+
166+
var newlyDeletedEntity = await _repository.Get((Guid)_entity.Id, true);
167+
Assert.IsTrue(success);
168+
Assert.IsTrue(newlyDeletedEntity.Deleted);
169+
Assert.NotNull(newlyDeletedEntity.DeletedAt);
170+
}
171+
172+
[Test]
173+
public void DeleteThrowsExceptionIfArgumentNull()
174+
{
175+
Assert.ThrowsAsync<ArgumentNullException>(() => _repository.Delete(null));
176+
}
177+
178+
[Test]
179+
public async Task DeleteWithValidIdDeletesAndSetsDeletedAt()
180+
{
181+
bool success;
182+
Guid id = (Guid)_entity.Id;
183+
using (_repository)
184+
{
185+
success = await _repository.Delete(id);
186+
}
187+
188+
var newlyDeletedEntity = await _repository.Get(id, true);
189+
Assert.IsTrue(success);
190+
Assert.IsTrue(newlyDeletedEntity.Deleted);
191+
Assert.NotNull(newlyDeletedEntity.DeletedAt);
192+
}
193+
194+
[Test]
195+
[AutoData]
196+
public async Task DeleteWithInvalidIdReturnsFalse(Guid randomId)
197+
{
198+
bool success;
199+
200+
using(_repository)
201+
{
202+
success = await _repository.Delete(randomId);
203+
}
204+
205+
Assert.IsFalse(success);
206+
}
207+
208+
[Test]
209+
public void DeleteWithEmptyGuidThrowsException()
210+
{
211+
Assert.ThrowsAsync<ArgumentException>(() => _repository.Delete(Guid.Empty));
212+
}
213+
#endregion
214+
215+
#region Restore
216+
[Test]
217+
public async Task RestoreSetsDeletedFalse()
218+
{
219+
bool success;
220+
221+
using(_repository)
222+
{
223+
success = await _repository.Restore(_deletedEntity);
224+
}
225+
226+
var restoredEntity = await _repository.Get((Guid)_deletedEntity.Id);
227+
Assert.IsTrue(success);
228+
Assert.IsFalse(restoredEntity?.Deleted);
229+
}
230+
231+
[Test]
232+
public void RestoreThrowsExceptionWhenEntityNull()
233+
{
234+
Assert.ThrowsAsync<ArgumentNullException>(() => _repository.Restore(null));
235+
}
236+
237+
[Test]
238+
public async Task RestoreOnIdSetsDeletedFalse()
239+
{
240+
bool success;
241+
Guid id = (Guid)_deletedEntity.Id;
242+
243+
using (_repository)
244+
{
245+
success = await _repository.Restore(id);
246+
}
247+
248+
var restoredEntity = await _repository.Get(id);
249+
Assert.IsTrue(success);
250+
Assert.IsFalse(restoredEntity?.Deleted);
251+
}
252+
253+
[Test]
254+
[AutoData]
255+
public async Task RestoreOnInvalidIdReturnsFalse(Guid randomId)
256+
{
257+
bool success;
258+
259+
using(_repository)
260+
{
261+
success = await _repository.Restore(randomId);
262+
}
263+
264+
Assert.IsFalse(success);
265+
}
266+
267+
[Test]
268+
public void RestoreOnEmptyGuidThrowsException()
269+
{
270+
Assert.ThrowsAsync<ArgumentException>(() => _repository.Restore(Guid.Empty));
271+
}
272+
#endregion
273+
}
274+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using Microsoft.EntityFrameworkCore;
2+
3+
namespace Nodes.NetCore.EntityFramework.Tests.Mocks
4+
{
5+
public class TestContext : DbContext
6+
{
7+
public TestContext(DbContextOptions options) : base(options) { }
8+
9+
public DbSet<TestEntity> Table { get; set; }
10+
}
11+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using Nodes.NetCore.EntityFramework.Models;
2+
3+
namespace Nodes.NetCore.EntityFramework.Tests.Mocks
4+
{
5+
public class TestEntity : EntityBase
6+
{
7+
public string Property { get; set; }
8+
}
9+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using Nodes.NetCore.EntityFramework.Repositories;
2+
3+
namespace Nodes.NetCore.EntityFramework.Tests.Mocks
4+
{
5+
public class TestEntityRepository : EntityRepository<TestEntity, TestContext>
6+
{
7+
public TestEntityRepository(TestContext context) : base(context, context.Table)
8+
{
9+
}
10+
}
11+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netcoreapp3.1</TargetFramework>
5+
6+
<IsPackable>false</IsPackable>
7+
8+
<AssemblyName>Nodes.NetCore.EntityFramework.Tests</AssemblyName>
9+
10+
<RootNamespace>Nodes.NetCore.EntityFramework.Tests</RootNamespace>
11+
</PropertyGroup>
12+
13+
<ItemGroup>
14+
<PackageReference Include="AutoFixture.NUnit3" Version="4.11.0" />
15+
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.1.3" />
16+
<PackageReference Include="nunit" Version="3.12.0" />
17+
<PackageReference Include="NUnit3TestAdapter" Version="3.16.1">
18+
<PrivateAssets>all</PrivateAssets>
19+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
20+
</PackageReference>
21+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
22+
</ItemGroup>
23+
24+
<ItemGroup>
25+
<ProjectReference Include="..\NetCoreEntityFramework\NetCoreEntityFramework.csproj" />
26+
</ItemGroup>
27+
28+
</Project>

NetCoreEntityFramework.sln

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio Version 16
44
VisualStudioVersion = 16.0.29905.134
55
MinimumVisualStudioVersion = 10.0.40219.1
6-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetCoreEntityFramework", "NetCoreEntityFramework\NetCoreEntityFramework.csproj", "{30F23EBE-4571-4215-8D70-F776A71BA51E}"
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetCoreEntityFramework", "NetCoreEntityFramework\NetCoreEntityFramework.csproj", "{30F23EBE-4571-4215-8D70-F776A71BA51E}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetCoreEntityFramework.Tests", "NetCoreEntityFramework.Tests\NetCoreEntityFramework.Tests.csproj", "{170EDF01-1CAD-49CF-9837-D0076667247B}"
79
EndProject
810
Global
911
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -15,6 +17,10 @@ Global
1517
{30F23EBE-4571-4215-8D70-F776A71BA51E}.Debug|Any CPU.Build.0 = Debug|Any CPU
1618
{30F23EBE-4571-4215-8D70-F776A71BA51E}.Release|Any CPU.ActiveCfg = Release|Any CPU
1719
{30F23EBE-4571-4215-8D70-F776A71BA51E}.Release|Any CPU.Build.0 = Release|Any CPU
20+
{170EDF01-1CAD-49CF-9837-D0076667247B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{170EDF01-1CAD-49CF-9837-D0076667247B}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{170EDF01-1CAD-49CF-9837-D0076667247B}.Release|Any CPU.ActiveCfg = Release|Any CPU
23+
{170EDF01-1CAD-49CF-9837-D0076667247B}.Release|Any CPU.Build.0 = Release|Any CPU
1824
EndGlobalSection
1925
GlobalSection(SolutionProperties) = preSolution
2026
HideSolutionNode = FALSE

NetCoreEntityFramework/Models/EntityBase.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using Microsoft.EntityFrameworkCore;
2-
using System;
1+
using System;
32
using System.ComponentModel.DataAnnotations;
43
using System.ComponentModel.DataAnnotations.Schema;
54

0 commit comments

Comments
 (0)