172 lines
6.1 KiB
C#
172 lines
6.1 KiB
C#
using System.ComponentModel.DataAnnotations.Schema;
|
|
using System.Reflection;
|
|
using e_suite.Database.Audit.Attributes;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using NUnit.Framework;
|
|
|
|
namespace e_suite.Database.Core.UnitTests;
|
|
|
|
[TestFixture]
|
|
public class TableDefinitionUnitTests
|
|
{
|
|
protected List<Type> Tables { get; set; } = [];
|
|
|
|
private static CustomAttributeData? FindAttribute(Type type, Type attributeType)
|
|
{
|
|
return type.CustomAttributes.FirstOrDefault(customAttribute => attributeType.IsAssignableFrom(customAttribute.AttributeType));
|
|
}
|
|
|
|
private static CustomAttributeData? FindAttribute(PropertyInfo propertyInfo, Type type)
|
|
{
|
|
return propertyInfo.CustomAttributes.FirstOrDefault(customAttribute => type.IsAssignableFrom(customAttribute.AttributeType));
|
|
}
|
|
|
|
private static List<string> CompileAcceptableTableNames(string tableName)
|
|
{
|
|
var result = new List<string>();
|
|
|
|
var lastCharactor = tableName[^1..];
|
|
var lastTwoCharactors = tableName[^2..];
|
|
|
|
if (lastTwoCharactors.Equals("ey", StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
result.Add(tableName + "s");
|
|
}
|
|
else if (lastCharactor.Equals("y", StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
result.Add(string.Concat(tableName.AsSpan(0, tableName.Length - 1), "ies"));
|
|
}
|
|
else if (lastCharactor.Equals("s", StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
result.Add(tableName);
|
|
}
|
|
else
|
|
{
|
|
result.Add(tableName + "s");
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
[SetUp]
|
|
public void Setup()
|
|
{
|
|
Tables.Clear();
|
|
var databaseContextClass = typeof(EsuiteDatabaseDbContext);
|
|
|
|
var properties = databaseContextClass.GetProperties();
|
|
foreach (var property in properties)
|
|
{
|
|
if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>))
|
|
{
|
|
Tables.Add(property.PropertyType.GenericTypeArguments[0]);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
[Test]
|
|
public void Table_PropertyHasAuditParentAttribute_AlsoHasForeignKey()
|
|
{
|
|
//Arrange
|
|
//Act
|
|
foreach (var table in Tables)
|
|
{
|
|
//Need to check all the properties of the table to see if it contains the AuditParent Custom property
|
|
var properties = table.GetProperties();
|
|
|
|
foreach (var property in properties)
|
|
{
|
|
if (FindAttribute(property, typeof(AuditParentAttribute)) != null)
|
|
{
|
|
//Assert
|
|
if (FindAttribute(property, typeof(ForeignKeyAttribute)) != null)
|
|
Assert.Pass($"Property {property.Name} Has both AuditParentAttribute And ForeignKey attribute");
|
|
else
|
|
Assert.Fail($"Property {property.Name} Has AuditParentAttribute but is missing the ForeignKey attribute");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void Table_TableName_IsSetConsistently()
|
|
{
|
|
//Arrange
|
|
//Act
|
|
foreach (var table in Tables)
|
|
{
|
|
//Need to check all the properties of the table to see if it contains the AuditParent Custom property
|
|
var tableAttribute = FindAttribute(table, typeof(TableAttribute));
|
|
|
|
//Assert
|
|
if (tableAttribute == null)
|
|
Assert.Fail($"Table \"{table.Name}\" Missing the TableNameAttribute");
|
|
|
|
var acceptableTableNames = CompileAcceptableTableNames(table.Name);
|
|
|
|
var tableName = tableAttribute?.ConstructorArguments[0].Value?.ToString() ?? string.Empty;
|
|
|
|
if (!acceptableTableNames.Contains(tableName))
|
|
Assert.Fail($"Table name \"{tableName}\" for class \"{table.Name}\" does not conform to the naming standards");
|
|
|
|
var schemaName = tableAttribute!.NamedArguments.Single( x=> x.MemberName == "Schema");
|
|
var tableNamespace = table.Namespace?.Split(".");
|
|
if (tableNamespace != null && tableNamespace.Last() != schemaName.TypedValue.Value?.ToString())
|
|
Assert.Fail($"Schema name for \"{table.Name}\" set incorrectly is currently \"{schemaName.TypedValue.Value}\" but should be \"{tableNamespace}\"");
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void Table_AuditedTables_HasLastUpdated()
|
|
{
|
|
//Arrange
|
|
//Act
|
|
foreach (var table in Tables)
|
|
{
|
|
//Assert
|
|
var tableAttribute = FindAttribute(table, typeof(TableAttribute));
|
|
if (tableAttribute == null)
|
|
continue;
|
|
|
|
//Need to check all the properties of the table to see if it contains the AuditParent Custom property
|
|
var noAuditAttribute = FindAttribute(table, typeof(NoAuditAttribute));
|
|
if (noAuditAttribute != null)
|
|
continue;
|
|
|
|
var foundLastUpdated = false;
|
|
var properties = table.GetProperties();
|
|
foreach (var property in properties)
|
|
{
|
|
if (FindAttribute(property, typeof(AuditLastUpdatedAttribute)) != null)
|
|
{
|
|
foundLastUpdated = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!foundLastUpdated)
|
|
Assert.Fail($"Table {table.Name} Missing {nameof(AuditLastUpdatedAttribute)}");
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void Table_ForeignKeysAreVirtual()
|
|
{
|
|
//Arrange
|
|
//Act
|
|
foreach (var table in Tables)
|
|
{
|
|
var properties = table.GetProperties();
|
|
foreach (var property in properties)
|
|
{
|
|
if (FindAttribute(property, typeof(ForeignKeyAttribute)) != null)
|
|
{
|
|
//Assert
|
|
if (!property.GetAccessors().Any( x=> x.IsVirtual))
|
|
Assert.Fail($"Table {table.Name}.{property.Name} is not virtual");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |