Skip to content
This repository was archived by the owner on Aug 7, 2020. It is now read-only.

Commit 816fd82

Browse files
authored
Model Unit tests (#27)
* Added unit tests for models * New and better error messages * Faked the database with [Entity Framework Effort](https://entityframework-effort.net/)
1 parent 3cf490a commit 816fd82

File tree

14 files changed

+1209
-36
lines changed

14 files changed

+1209
-36
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// NUnit 3 tests
2+
// See documentation : https://github.com/nunit/docs/wiki/NUnit-Documentation
3+
4+
using System.Data.SqlClient;
5+
using System.Linq;
6+
using Effort;
7+
using NMemory.Linq;
8+
using NUnit.Framework;
9+
10+
namespace AlwaysEncryptedSample.Models
11+
{
12+
public abstract class AbstractModelTests
13+
{
14+
protected AuthDbContext AuthCtx { get; private set; }
15+
protected ApplicationDbContext AppCtx { get; private set; }
16+
17+
[OneTimeSetUp]
18+
public void Setup()
19+
{
20+
var connection = DbConnectionFactory.CreateTransient();
21+
AuthCtx = new AuthDbContext(connection);
22+
AppCtx = new ApplicationDbContext(connection);
23+
24+
}
25+
}
26+
27+
[TestFixture]
28+
public class ApplicationTests : AbstractModelTests
29+
{
30+
[Test]
31+
public void TestAddCreditCard()
32+
{
33+
var cc = AppCtx.CreditCards.Create();
34+
cc.CardNumber = "xxxx-xxxx-xxxx-xxxx";
35+
cc.CCV = 128;
36+
cc.ExpMonth = 4;
37+
cc.ExpYear = 2022;
38+
cc.Network = new CreditCardNetwork
39+
{
40+
Name = "Visa"
41+
};
42+
AppCtx.CreditCards.Add(cc);
43+
AppCtx.SaveChanges();
44+
Assert.AreEqual(1,AppCtx.CreditCards.Count(c => c.CardNumber == "xxxx-xxxx-xxxx-xxxx"));
45+
Assert.AreEqual(1,AppCtx.CreditCardNetworks.Count(n => n.Name== "Visa"));
46+
}
47+
}
48+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="16.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="..\packages\NUnit3TestAdapter.3.13.0\build\net35\NUnit3TestAdapter.props" Condition="Exists('..\packages\NUnit3TestAdapter.3.13.0\build\net35\NUnit3TestAdapter.props')" />
4+
<Import Project="..\packages\NUnit.3.11.0\build\NUnit.props" Condition="Exists('..\packages\NUnit.3.11.0\build\NUnit.props')" />
5+
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
6+
<PropertyGroup>
7+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
8+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
9+
<ProjectGuid>{8EDF4429-251A-416D-BB68-93F227191BCF}</ProjectGuid>
10+
<OutputType>Library</OutputType>
11+
<AppDesignerFolder>Properties</AppDesignerFolder>
12+
<RootNamespace>AlwaysEncryptedSample.Models</RootNamespace>
13+
<AssemblyName>AlwaysEncryptedSample.Models.Tests</AssemblyName>
14+
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
15+
<FileAlignment>512</FileAlignment>
16+
<NuGetPackageImportStamp>
17+
</NuGetPackageImportStamp>
18+
<TargetFrameworkProfile />
19+
</PropertyGroup>
20+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
21+
<DebugSymbols>true</DebugSymbols>
22+
<DebugType>full</DebugType>
23+
<Optimize>false</Optimize>
24+
<OutputPath>bin\Debug\</OutputPath>
25+
<DefineConstants>DEBUG;TRACE</DefineConstants>
26+
<ErrorReport>prompt</ErrorReport>
27+
<WarningLevel>4</WarningLevel>
28+
</PropertyGroup>
29+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
30+
<DebugType>pdbonly</DebugType>
31+
<Optimize>true</Optimize>
32+
<OutputPath>bin\Release\</OutputPath>
33+
<DefineConstants>TRACE</DefineConstants>
34+
<ErrorReport>prompt</ErrorReport>
35+
<WarningLevel>4</WarningLevel>
36+
</PropertyGroup>
37+
<ItemGroup>
38+
<Reference Include="Effort, Version=2.1.0.0, Culture=neutral, PublicKeyToken=6a46696d54971e6d, processorArchitecture=MSIL">
39+
<HintPath>..\packages\Effort.EF6.2.1.0\lib\net45\Effort.dll</HintPath>
40+
</Reference>
41+
<Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
42+
<HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll</HintPath>
43+
</Reference>
44+
<Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
45+
<HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
46+
</Reference>
47+
<Reference Include="NMemory, Version=3.0.0.0, Culture=neutral, PublicKeyToken=afc61983f100d280, processorArchitecture=MSIL">
48+
<HintPath>..\packages\NMemory.3.1.0\lib\net45\NMemory.dll</HintPath>
49+
</Reference>
50+
<Reference Include="nunit.framework, Version=3.11.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
51+
<HintPath>..\packages\NUnit.3.11.0\lib\net45\nunit.framework.dll</HintPath>
52+
</Reference>
53+
<Reference Include="System" />
54+
<Reference Include="System.ComponentModel.DataAnnotations" />
55+
<Reference Include="System.Data" />
56+
<Reference Include="System.Data.SqlClient, Version=4.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
57+
<HintPath>..\packages\System.Data.SqlClient.4.6.0\lib\net461\System.Data.SqlClient.dll</HintPath>
58+
</Reference>
59+
<Reference Include="System.Xml" />
60+
</ItemGroup>
61+
<ItemGroup>
62+
<Compile Include="AbstractModelTests.cs" />
63+
<Compile Include="CreditCardTests.cs" />
64+
</ItemGroup>
65+
<ItemGroup>
66+
<None Include="app.config" />
67+
<None Include="packages.config" />
68+
</ItemGroup>
69+
<ItemGroup>
70+
<ProjectReference Include="..\AlwaysEncryptedSample.Models\AlwaysEncryptedSample.Models.csproj">
71+
<Project>{6f9599eb-3c9a-45ad-a081-30f83946d63c}</Project>
72+
<Name>AlwaysEncryptedSample.Models</Name>
73+
</ProjectReference>
74+
</ItemGroup>
75+
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
76+
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
77+
<PropertyGroup>
78+
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
79+
</PropertyGroup>
80+
<Error Condition="!Exists('..\packages\NUnit.3.11.0\build\NUnit.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NUnit.3.11.0\build\NUnit.props'))" />
81+
<Error Condition="!Exists('..\packages\NUnit3TestAdapter.3.13.0\build\net35\NUnit3TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NUnit3TestAdapter.3.13.0\build\net35\NUnit3TestAdapter.props'))" />
82+
</Target>
83+
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
84+
Other similar extension points exist, see Microsoft.Common.targets.
85+
<Target Name="BeforeBuild">
86+
</Target>
87+
<Target Name="AfterBuild">
88+
</Target>
89+
-->
90+
</Project>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System;
2+
using NUnit.Framework;
3+
4+
namespace AlwaysEncryptedSample.Models
5+
{
6+
[TestFixture]
7+
public class CreditCardTests
8+
{
9+
[Test]
10+
public void TestConstructor()
11+
{
12+
var creditCard = new CreditCard();
13+
Assert.GreaterOrEqual(1, (DateTime.Now - creditCard.ModifiedDate).Seconds);
14+
Assert.AreEqual(0,creditCard.CreditCardId);
15+
Assert.AreEqual(0,creditCard.CCV);
16+
Assert.AreEqual(0, creditCard.ExpMonth);
17+
Assert.AreEqual(0, creditCard.ExpYear);
18+
Assert.IsNull(creditCard.CardNumber);
19+
}
20+
}
21+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<configSections>
4+
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
5+
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections>
6+
<entityFramework>
7+
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
8+
<parameters>
9+
<parameter value="mssqllocaldb" />
10+
</parameters>
11+
</defaultConnectionFactory>
12+
<providers>
13+
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
14+
</providers>
15+
</entityFramework>
16+
<runtime>
17+
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
18+
<dependentAssembly>
19+
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
20+
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
21+
</dependentAssembly>
22+
<dependentAssembly>
23+
<assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" culture="neutral" />
24+
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
25+
</dependentAssembly>
26+
<dependentAssembly>
27+
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
28+
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
29+
</dependentAssembly>
30+
<dependentAssembly>
31+
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
32+
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
33+
</dependentAssembly>
34+
<dependentAssembly>
35+
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
36+
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
37+
</dependentAssembly>
38+
</assemblyBinding>
39+
</runtime>
40+
</configuration>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<packages>
3+
<package id="Effort.EF6" version="2.1.0" targetFramework="net461" />
4+
<package id="EntityFramework" version="6.2.0" targetFramework="net461" />
5+
<package id="NMemory" version="3.1.0" targetFramework="net461" />
6+
<package id="NUnit" version="3.11.0" targetFramework="net461" />
7+
<package id="NUnit3TestAdapter" version="3.13.0" targetFramework="net461" />
8+
<package id="System.Data.SqlClient" version="4.6.0" targetFramework="net461" />
9+
</packages>

AlwaysEncryptedSample.Models/ApplicationDbContext.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
1+
using System.Data.Common;
12
using System.Data.Entity;
23
using AlwaysEncryptedSample.Models.Properties;
34

45
namespace AlwaysEncryptedSample.Models
56
{
67
public class ApplicationDbContext : DbContext
78
{
8-
/// <remarks>Use DefaultConnection so we use one connection string for this and the ASP.NET authnetication.</remarks>
9+
/// <remarks>Use DefaultConnection so we use one connection string for this and the ASP.NET authentication.</remarks>
910
public ApplicationDbContext(string nameOrConnectionString)
1011
: base(nameOrConnectionString)
1112
{
1213
}
1314

15+
/// <remarks>Constructor for unit testing.</remarks>
16+
internal ApplicationDbContext(DbConnection connection)
17+
: base(connection, false)
18+
{
19+
}
20+
1421
public static ApplicationDbContext Create(string nameOrConnectionString = "DefaultConnection")
1522
{
1623
return new ApplicationDbContext(nameOrConnectionString);

AlwaysEncryptedSample.Models/AuthDbContext.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Data.Common;
12
using System.Data.Entity;
23
using AlwaysEncryptedSample.Models.Properties;
34
using Microsoft.AspNet.Identity.EntityFramework;
@@ -11,6 +12,12 @@ public AuthDbContext(string nameOrConnectionString)
1112
{
1213
}
1314

15+
/// <remarks>Constructor for unit testing.</remarks>
16+
internal AuthDbContext(DbConnection connection)
17+
: base(connection, false)
18+
{
19+
}
20+
1421
public static AuthDbContext Create()
1522
{
1623
return Create("name=DefaultConnection");

AlwaysEncryptedSample.Models/CreditCard.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ public class CreditCard
88
{
99
public CreditCard()
1010
{
11-
ModifiedDate = DateTime.Now;
11+
//TODO: This is probably completely broken an needs tests to prove out.
12+
//Need to force this field modified to DateTime.Now every send.
13+
ModifiedDate = DateTime.UtcNow;
1214
}
1315

1416
[Key]
@@ -24,6 +26,7 @@ public CreditCard()
2426
[Required]
2527
public short ExpYear { get; set; }
2628
[Required]
29+
// ReSharper disable once InconsistentNaming
2730
public short CCV { get; set; }
2831
[Required]
2932
public DateTime ModifiedDate { get; set; }

AlwaysEncryptedSample.Models/DbInit.cs

Lines changed: 39 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Data;
4+
using System.Data.Entity.Infrastructure;
45
using System.Data.SqlClient;
56
using System.Linq;
67
using System.Reflection;
@@ -25,44 +26,49 @@ public static void CreateAuthContext(string nameOrConnectionString = "DefaultCon
2526
{
2627
using (var authDbCtx = AuthDbContext.Create(nameOrConnectionString))
2728
{
28-
authDbCtx.Database.Log = (dbLog => log.Debug(dbLog));
29-
log.Info("Initialization tests for Authorization Schema");
30-
if (!authDbCtx.Roles.Any())
31-
{
32-
log.Info("No roles found in database. Creating roles");
33-
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(authDbCtx));
34-
roleManager.Create(new IdentityRole("DBAs")); // Gives database internals access
35-
roleManager.Create(new IdentityRole("Credit Card Admins")); // Gives access to CC info
36-
}
29+
InitDbContext(authDbCtx);
30+
}
31+
}
3732

38-
if (!authDbCtx.Users.Any())
39-
{
40-
log.Info("No users found in database. Creating users");
41-
var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(authDbCtx));
42-
userManager.Create(new ApplicationUser
43-
{
44-
Id = "Administrator",
45-
Email = "[email protected]",
46-
UserName = "Administrator",
47-
EmailConfirmed = true,
48-
PasswordHash = userManager.PasswordHasher.HashPassword("Alm0nds!"),
49-
});
33+
private static void InitDbContext(AuthDbContext authDbCtx)
34+
{
35+
authDbCtx.Database.Log = (dbLog => log.Debug(dbLog));
36+
log.Info("Initialization tests for Authorization Schema");
37+
if (!authDbCtx.Roles.Any())
38+
{
39+
log.Info("No roles found in database. Creating roles");
40+
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(authDbCtx));
41+
roleManager.Create(new IdentityRole("DBAs")); // Gives database internals access
42+
roleManager.Create(new IdentityRole("Credit Card Admins")); // Gives access to CC info
43+
}
5044

51-
userManager.AddToRole("Administrator", "DBAs");
45+
if (!authDbCtx.Users.Any())
46+
{
47+
log.Info("No users found in database. Creating users");
48+
var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(authDbCtx));
49+
userManager.Create(new ApplicationUser
50+
{
51+
Id = "Administrator",
52+
Email = "[email protected]",
53+
UserName = "Administrator",
54+
EmailConfirmed = true,
55+
PasswordHash = userManager.PasswordHasher.HashPassword("Alm0nds!"),
56+
});
5257

53-
userManager.Create(new ApplicationUser
54-
{
55-
Email = "[email protected]",
56-
Id = "CCAdmin",
57-
UserName = "CCAdmin",
58-
EmailConfirmed = true,
59-
PasswordHash = userManager.PasswordHasher.HashPassword("Appl3s")
60-
});
61-
userManager.AddToRole("CCAdmin", "Credit Card Admins");
62-
}
58+
userManager.AddToRole("Administrator", "DBAs");
6359

64-
authDbCtx.SaveChanges();
60+
userManager.Create(new ApplicationUser
61+
{
62+
Email = "[email protected]",
63+
Id = "CCAdmin",
64+
UserName = "CCAdmin",
65+
EmailConfirmed = true,
66+
PasswordHash = userManager.PasswordHasher.HashPassword("Appl3s")
67+
});
68+
userManager.AddToRole("CCAdmin", "Credit Card Admins");
6569
}
70+
71+
authDbCtx.SaveChanges();
6672
}
6773

6874
/// <summary>

AlwaysEncryptedSample.Models/Properties/AssemblyInfo.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Reflection;
2+
using System.Runtime.CompilerServices;
23
using System.Runtime.InteropServices;
34

45
// General Information about an assembly is controlled through the following
@@ -8,4 +9,6 @@
89
[assembly: AssemblyDescription("EF Core 6 and Asp.Net Identity Object models for the AlwaysEncryptedSample. ")]
910

1011
[assembly: ComVisible(false)]
11-
[assembly: Guid("6f9599eb-3c9a-45ad-a081-30f83946d63c")]
12+
[assembly: Guid("6f9599eb-3c9a-45ad-a081-30f83946d63c")]
13+
14+
[assembly:InternalsVisibleTo("AlwaysEncryptedSample.Models.Tests")]

0 commit comments

Comments
 (0)