Skip to content

Commit d1f372e

Browse files
Copilotmrdevrobot
andcommitted
Add comprehensive unit tests for core components - 69 tests passing
Co-authored-by: lucafabbri <12503462+lucafabbri@users.noreply.github.com>
1 parent 32146fc commit d1f372e

75 files changed

Lines changed: 12898 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

ProjectR.Tests/DiagnosticsTests.cs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
using FluentAssertions;
2+
using Microsoft.CodeAnalysis;
3+
using Xunit;
4+
5+
namespace ProjectR.Tests.Diagnostic;
6+
7+
public class DiagnosticsTests
8+
{
9+
[Fact]
10+
public void UnexpectedError_HasCorrectProperties()
11+
{
12+
// Arrange & Act
13+
var diagnostic = ProjectR.Diagnostics.UnexpectedError;
14+
15+
// Assert
16+
diagnostic.Id.Should().Be("PR0001");
17+
diagnostic.Title.ToString().Should().Be("An unexpected error occurred");
18+
diagnostic.MessageFormat.ToString().Should().Be("An unexpected error occurred during mapper generation: '{0}' StackTrace: {1}");
19+
diagnostic.Category.Should().Be("ProjectR.Generator");
20+
diagnostic.DefaultSeverity.Should().Be(DiagnosticSeverity.Error);
21+
diagnostic.IsEnabledByDefault.Should().BeTrue();
22+
}
23+
24+
[Fact]
25+
public void MapperGenerationFailed_HasCorrectProperties()
26+
{
27+
// Arrange & Act
28+
var diagnostic = ProjectR.Diagnostics.MapperGenerationFailed;
29+
30+
// Assert
31+
diagnostic.Id.Should().Be("PR0002");
32+
diagnostic.Title.ToString().Should().Be("Mapper generation failed");
33+
diagnostic.MessageFormat.ToString().Should().Be("Failed to generate an implementation for mapper '{0}'");
34+
diagnostic.Category.Should().Be("ProjectR.Generator");
35+
diagnostic.DefaultSeverity.Should().Be(DiagnosticSeverity.Error);
36+
diagnostic.IsEnabledByDefault.Should().BeTrue();
37+
}
38+
39+
[Fact]
40+
public void NoValidCreationMethod_HasCorrectProperties()
41+
{
42+
// Arrange & Act
43+
var diagnostic = ProjectR.Diagnostics.NoValidCreationMethod;
44+
45+
// Assert
46+
diagnostic.Id.Should().Be("PR0003");
47+
diagnostic.Title.ToString().Should().Be("No valid creation method found");
48+
diagnostic.MessageFormat.ToString().Should().Be("ProjectR could not find a valid constructor or static factory method to create an instance of '{0}' based on the source type.");
49+
diagnostic.Category.Should().Be("ProjectR.Policies");
50+
diagnostic.DefaultSeverity.Should().Be(DiagnosticSeverity.Error);
51+
diagnostic.IsEnabledByDefault.Should().BeTrue();
52+
}
53+
54+
[Fact]
55+
public void UnmappableConstructorParameter_HasCorrectProperties()
56+
{
57+
// Arrange & Act
58+
var diagnostic = ProjectR.Diagnostics.UnmappableConstructorParameter;
59+
60+
// Assert
61+
diagnostic.Id.Should().Be("PR0004");
62+
diagnostic.Title.ToString().Should().Be("Unmappable constructor parameter");
63+
diagnostic.MessageFormat.ToString().Should().Be("The parameter '{0}' of the constructor for '{1}' could not be mapped from any source property.");
64+
diagnostic.Category.Should().Be("ProjectR.Policies");
65+
diagnostic.DefaultSeverity.Should().Be(DiagnosticSeverity.Error);
66+
diagnostic.IsEnabledByDefault.Should().BeTrue();
67+
}
68+
69+
[Fact]
70+
public void UnmappedDestinationProperty_HasCorrectProperties()
71+
{
72+
// Arrange & Act
73+
var diagnostic = ProjectR.Diagnostics.UnmappedDestinationProperty;
74+
75+
// Assert
76+
diagnostic.Id.Should().Be("PR0005");
77+
diagnostic.Title.ToString().Should().Be("Unmapped destination property");
78+
diagnostic.MessageFormat.ToString().Should().Be("The property '{0}' on destination type '{1}' was not mapped.");
79+
diagnostic.Category.Should().Be("ProjectR.Policies");
80+
diagnostic.DefaultSeverity.Should().Be(DiagnosticSeverity.Warning);
81+
diagnostic.IsEnabledByDefault.Should().BeTrue();
82+
}
83+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
using ProjectR.Attributes;
2+
using FluentAssertions;
3+
using Xunit;
4+
5+
namespace ProjectR.Tests.Attributes;
6+
7+
public class DtoAttributeTests
8+
{
9+
private class TestEntity { }
10+
private class TestDto { }
11+
private class TestMapper { }
12+
13+
[Fact]
14+
public void DtoAttribute_Constructor_SetsEntityTypeCorrectly()
15+
{
16+
// Arrange & Act
17+
var attribute = new DtoAttribute<TestEntity>();
18+
19+
// Assert
20+
attribute.EntityType.Should().Be(typeof(TestEntity));
21+
}
22+
23+
[Fact]
24+
public void DtoMapperAttribute_Constructor_SetsEntityTypeAndMapperTypeCorrectly()
25+
{
26+
// Arrange & Act
27+
var attribute = new DtoMapperAttribute<TestEntity, TestMapper>();
28+
29+
// Assert
30+
attribute.EntityType.Should().Be(typeof(TestEntity));
31+
attribute.MapperType.Should().Be(typeof(TestMapper));
32+
}
33+
34+
[Fact]
35+
public void DtoAttribute_HasCorrectAttributeUsage()
36+
{
37+
// Arrange & Act
38+
var attributeUsage = typeof(DtoAttribute<>).GetCustomAttributes(typeof(AttributeUsageAttribute), false)
39+
.Cast<AttributeUsageAttribute>()
40+
.First();
41+
42+
// Assert
43+
attributeUsage.ValidOn.Should().Be(AttributeTargets.Class);
44+
attributeUsage.AllowMultiple.Should().BeTrue();
45+
attributeUsage.Inherited.Should().BeTrue();
46+
}
47+
48+
[Fact]
49+
public void DtoMapperAttribute_HasCorrectAttributeUsage()
50+
{
51+
// Arrange & Act
52+
var attributeUsage = typeof(DtoMapperAttribute<,>).GetCustomAttributes(typeof(AttributeUsageAttribute), false)
53+
.Cast<AttributeUsageAttribute>()
54+
.First();
55+
56+
// Assert
57+
attributeUsage.ValidOn.Should().Be(AttributeTargets.Class);
58+
attributeUsage.AllowMultiple.Should().BeTrue();
59+
attributeUsage.Inherited.Should().BeTrue();
60+
}
61+
62+
[Fact]
63+
public void DtoMapperAttribute_InheritsFromDtoAttribute()
64+
{
65+
// Arrange & Act & Assert
66+
typeof(DtoMapperAttribute<TestEntity, TestMapper>).Should().BeDerivedFrom<DtoAttribute<TestEntity>>();
67+
}
68+
}

ProjectR.Tests/GlobalUsings.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
global using Xunit;
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
using FluentAssertions;
2+
using Microsoft.Extensions.DependencyInjection;
3+
using ProjectR.DI;
4+
using ProjectR.Services;
5+
using System.Reflection;
6+
using Xunit;
7+
8+
namespace ProjectR.Tests.DI;
9+
10+
public class MapperRegistrationExtensionsTests
11+
{
12+
private class TestEntity { }
13+
private class TestDto { }
14+
private class TestEntity2 { }
15+
private class TestDto2 { }
16+
17+
private class TestMapper : Mapper<TestEntity, TestDto>
18+
{
19+
public override TestDto Project(TestEntity source) => new TestDto();
20+
public override TestEntity Build(TestDto dto) => new TestEntity();
21+
public override void Apply(TestDto dto, TestEntity entityToUpdate) { }
22+
}
23+
24+
private class TestMapper2 : Mapper<TestEntity2, TestDto2>
25+
{
26+
public override TestDto2 Project(TestEntity2 source) => new TestDto2();
27+
public override TestEntity2 Build(TestDto2 dto) => new TestEntity2();
28+
public override void Apply(TestDto2 dto, TestEntity2 entityToUpdate) { }
29+
}
30+
31+
private abstract class AbstractMapper : Mapper<TestEntity, TestDto>
32+
{
33+
// Abstract class should be ignored during scanning
34+
}
35+
36+
private class NonMapperClass { }
37+
38+
public class MapperRegistryTests
39+
{
40+
[Fact]
41+
public void Constructor_WithAssemblyContainingMappers_FindsMappers()
42+
{
43+
// Arrange
44+
var assembly = Assembly.GetExecutingAssembly();
45+
46+
// Act
47+
var registry = new MapperRegistrationExtensions.MapperRegistry(new[] { assembly });
48+
49+
// Assert
50+
registry.FoundMappers.Should().NotBeEmpty();
51+
registry.FoundMappers.Should().Contain(typeof(TestMapper));
52+
registry.FoundMappers.Should().Contain(typeof(TestMapper2));
53+
}
54+
55+
[Fact]
56+
public void Constructor_WithAssemblyContainingMappers_IgnoresAbstractMappers()
57+
{
58+
// Arrange
59+
var assembly = Assembly.GetExecutingAssembly();
60+
61+
// Act
62+
var registry = new MapperRegistrationExtensions.MapperRegistry(new[] { assembly });
63+
64+
// Assert
65+
registry.FoundMappers.Should().NotContain(typeof(AbstractMapper));
66+
}
67+
68+
[Fact]
69+
public void Constructor_WithAssemblyContainingMappers_IgnoresNonMappers()
70+
{
71+
// Arrange
72+
var assembly = Assembly.GetExecutingAssembly();
73+
74+
// Act
75+
var registry = new MapperRegistrationExtensions.MapperRegistry(new[] { assembly });
76+
77+
// Assert
78+
registry.FoundMappers.Should().NotContain(typeof(NonMapperClass));
79+
registry.FoundMappers.Should().NotContain(typeof(string));
80+
}
81+
82+
[Fact]
83+
public void Constructor_WithEmptyAssemblyList_ReturnsEmptyCollection()
84+
{
85+
// Arrange
86+
var assemblies = Array.Empty<Assembly>();
87+
88+
// Act
89+
var registry = new MapperRegistrationExtensions.MapperRegistry(assemblies);
90+
91+
// Assert
92+
registry.FoundMappers.Should().BeEmpty();
93+
}
94+
95+
[Fact]
96+
public void FoundMappers_IsReadOnlyCollection()
97+
{
98+
// Arrange
99+
var assembly = Assembly.GetExecutingAssembly();
100+
var registry = new MapperRegistrationExtensions.MapperRegistry(new[] { assembly });
101+
102+
// Act & Assert
103+
registry.FoundMappers.Should().BeAssignableTo<IReadOnlyCollection<Type>>();
104+
}
105+
}
106+
107+
public class AddMappersExtensionTests
108+
{
109+
[Fact]
110+
public void AddMappers_WithValidAssembly_RegistersAllServices()
111+
{
112+
// Arrange
113+
var services = new ServiceCollection();
114+
var assembly = Assembly.GetExecutingAssembly();
115+
116+
// Act
117+
services.AddMappers(assembly);
118+
var serviceProvider = services.BuildServiceProvider();
119+
120+
// Assert
121+
// Check that MapperTypeCache is registered
122+
var cache = serviceProvider.GetService<MapperTypeCache>();
123+
cache.Should().NotBeNull();
124+
125+
// Check that IMapperResolver is registered
126+
var resolver = serviceProvider.GetService<IMapperResolver>();
127+
resolver.Should().NotBeNull();
128+
resolver.Should().BeOfType<MapperResolver>();
129+
130+
// Check that individual mappers are registered
131+
var mapper1 = serviceProvider.GetService<TestMapper>();
132+
mapper1.Should().NotBeNull();
133+
134+
var mapper2 = serviceProvider.GetService<TestMapper2>();
135+
mapper2.Should().NotBeNull();
136+
}
137+
138+
[Fact]
139+
public void AddMappers_WithNullAssemblies_UsesCallingAssembly()
140+
{
141+
// Arrange
142+
var services = new ServiceCollection();
143+
144+
// Act
145+
services.AddMappers(null!);
146+
var serviceProvider = services.BuildServiceProvider();
147+
148+
// Assert
149+
var resolver = serviceProvider.GetService<IMapperResolver>();
150+
resolver.Should().NotBeNull();
151+
}
152+
153+
[Fact]
154+
public void AddMappers_WithEmptyAssemblies_UsesCallingAssembly()
155+
{
156+
// Arrange
157+
var services = new ServiceCollection();
158+
159+
// Act
160+
services.AddMappers();
161+
var serviceProvider = services.BuildServiceProvider();
162+
163+
// Assert
164+
var resolver = serviceProvider.GetService<IMapperResolver>();
165+
resolver.Should().NotBeNull();
166+
}
167+
168+
[Fact]
169+
public void AddMappers_ReturnsServiceCollection_ForChaining()
170+
{
171+
// Arrange
172+
var services = new ServiceCollection();
173+
var assembly = Assembly.GetExecutingAssembly();
174+
175+
// Act
176+
var result = services.AddMappers(assembly);
177+
178+
// Assert
179+
result.Should().BeSameAs(services);
180+
}
181+
182+
[Fact]
183+
public void AddMappers_RegistersMapperTypeCacheAsSingleton()
184+
{
185+
// Arrange
186+
var services = new ServiceCollection();
187+
var assembly = Assembly.GetExecutingAssembly();
188+
189+
// Act
190+
services.AddMappers(assembly);
191+
var serviceProvider = services.BuildServiceProvider();
192+
193+
// Assert
194+
var cache1 = serviceProvider.GetService<MapperTypeCache>();
195+
var cache2 = serviceProvider.GetService<MapperTypeCache>();
196+
cache1.Should().BeSameAs(cache2);
197+
}
198+
199+
[Fact]
200+
public void AddMappers_RegistersIndividualMappersAsSingletons()
201+
{
202+
// Arrange
203+
var services = new ServiceCollection();
204+
var assembly = Assembly.GetExecutingAssembly();
205+
206+
// Act
207+
services.AddMappers(assembly);
208+
var serviceProvider = services.BuildServiceProvider();
209+
210+
// Assert
211+
var mapper1a = serviceProvider.GetService<TestMapper>();
212+
var mapper1b = serviceProvider.GetService<TestMapper>();
213+
mapper1a.Should().BeSameAs(mapper1b);
214+
}
215+
216+
[Fact]
217+
public void AddMappers_RegistersResolverAsSingleton()
218+
{
219+
// Arrange
220+
var services = new ServiceCollection();
221+
var assembly = Assembly.GetExecutingAssembly();
222+
223+
// Act
224+
services.AddMappers(assembly);
225+
var serviceProvider = services.BuildServiceProvider();
226+
227+
// Assert
228+
var resolver1 = serviceProvider.GetService<IMapperResolver>();
229+
var resolver2 = serviceProvider.GetService<IMapperResolver>();
230+
resolver1.Should().BeSameAs(resolver2);
231+
}
232+
}
233+
}

0 commit comments

Comments
 (0)