Skip to content

Commit af0f9d2

Browse files
committed
add acceptance tests
1 parent 60191a8 commit af0f9d2

23 files changed

+453
-38
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,3 +350,5 @@ MigrationBackup/
350350
.ionide/
351351

352352
.idea
353+
354+
.received.txt

Injectio.sln

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# 17
3+
# Visual Studio Version 17
44
VisualStudioVersion = 17.0.31903.59
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{C2680CC3-2014-44BE-98B2-D4431437E0A1}"
@@ -23,6 +23,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Injectio.Tests.Console", "t
2323
EndProject
2424
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Injectio.Tests", "tests\Injectio.Tests\Injectio.Tests.csproj", "{00F3B7F0-79F0-47FD-B534-88DD4337A18B}"
2525
EndProject
26+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Injectio.Acceptance.Tests", "tests\Injectio.Acceptance.Tests\Injectio.Acceptance.Tests.csproj", "{0E7E3A47-C734-4B41-9B56-7ABD8F611A15}"
27+
EndProject
2628
Global
2729
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2830
Debug|Any CPU = Debug|Any CPU
@@ -49,6 +51,10 @@ Global
4951
{00F3B7F0-79F0-47FD-B534-88DD4337A18B}.Debug|Any CPU.Build.0 = Debug|Any CPU
5052
{00F3B7F0-79F0-47FD-B534-88DD4337A18B}.Release|Any CPU.ActiveCfg = Release|Any CPU
5153
{00F3B7F0-79F0-47FD-B534-88DD4337A18B}.Release|Any CPU.Build.0 = Release|Any CPU
54+
{0E7E3A47-C734-4B41-9B56-7ABD8F611A15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
55+
{0E7E3A47-C734-4B41-9B56-7ABD8F611A15}.Debug|Any CPU.Build.0 = Debug|Any CPU
56+
{0E7E3A47-C734-4B41-9B56-7ABD8F611A15}.Release|Any CPU.ActiveCfg = Release|Any CPU
57+
{0E7E3A47-C734-4B41-9B56-7ABD8F611A15}.Release|Any CPU.Build.0 = Release|Any CPU
5258
EndGlobalSection
5359
GlobalSection(SolutionProperties) = preSolution
5460
HideSolutionNode = FALSE
@@ -57,6 +63,7 @@ Global
5763
{53520262-91C3-4B49-B8CE-1EAAC516A86B} = {4A8CBCD4-2F78-466D-B60B-B983BAA90B5A}
5864
{5D7F57EA-10F4-4F76-8B4B-DD8C69FB3CD3} = {4A8CBCD4-2F78-466D-B60B-B983BAA90B5A}
5965
{00F3B7F0-79F0-47FD-B534-88DD4337A18B} = {4A8CBCD4-2F78-466D-B60B-B983BAA90B5A}
66+
{0E7E3A47-C734-4B41-9B56-7ABD8F611A15} = {4A8CBCD4-2F78-466D-B60B-B983BAA90B5A}
6067
EndGlobalSection
6168
GlobalSection(ExtensibilityGlobals) = postSolution
6269
SolutionGuid = {E3E7D87C-946B-477C-803F-E7663074492F}

src/Injectio.Generators/ServiceRegistrationWriter.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,8 @@ private static void WriteServiceGeneric(
296296
{
297297
codeBuilder
298298
.AppendIf(", ", serviceRegistration.ServiceKey.HasValue())
299+
.AppendLine()
300+
.IncrementIndent()
299301
.Append("(serviceProvider")
300302
.AppendIf(", key", serviceRegistration.ServiceKey.HasValue())
301303
.Append(") => global::Microsoft.Extensions.DependencyInjection.ServiceProvider")
@@ -306,7 +308,9 @@ private static void WriteServiceGeneric(
306308
.Append(serviceRegistration.ImplementationType)
307309
.Append(">(serviceProvider")
308310
.AppendIf(", key", serviceRegistration.ServiceKey.HasValue())
309-
.Append(")");
311+
.Append(")")
312+
.AppendLine()
313+
.DecrementIndent();
310314
}
311315

312316
codeBuilder
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using Xunit.Abstractions;
2+
3+
using XUnit.Hosting;
4+
5+
namespace Injectio.Acceptance.Tests;
6+
7+
[Collection(DependencyInjectionCollection.CollectionName)]
8+
public abstract class DependencyInjectionBase(ITestOutputHelper output, DependencyInjectionFixture fixture)
9+
: TestHostBase<DependencyInjectionFixture>(output, fixture)
10+
{
11+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace Injectio.Acceptance.Tests;
2+
3+
[CollectionDefinition(CollectionName)]
4+
public class DependencyInjectionCollection : ICollectionFixture<DependencyInjectionFixture>
5+
{
6+
public const string CollectionName = nameof(DependencyInjectionCollection);
7+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
using Microsoft.Extensions.Hosting;
3+
4+
using XUnit.Hosting;
5+
6+
namespace Injectio.Acceptance.Tests;
7+
8+
public class DependencyInjectionFixture : TestApplicationFixture
9+
{
10+
protected override void ConfigureApplication(HostApplicationBuilder builder)
11+
{
12+
base.ConfigureApplication(builder);
13+
14+
var services = builder.Services;
15+
16+
services.AddInjectioTestsLibrary("Alpha", "Beta");
17+
services.AddInjectioAcceptanceTests("Alpha", "Beta");
18+
}
19+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net9.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
<IsPackable>false</IsPackable>
8+
</PropertyGroup>
9+
10+
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
11+
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
12+
</PropertyGroup>
13+
14+
<ItemGroup>
15+
<PackageReference Include="AwesomeAssertions" Version="8.1.0" />
16+
<PackageReference Include="coverlet.collector" Version="6.0.4">
17+
<PrivateAssets>all</PrivateAssets>
18+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
19+
</PackageReference>
20+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
21+
<PackageReference Include="xunit" Version="2.9.3" />
22+
<PackageReference Include="XUnit.Hosting" Version="2.0.0" />
23+
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.2">
24+
<PrivateAssets>all</PrivateAssets>
25+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
26+
</PackageReference>
27+
</ItemGroup>
28+
29+
<ItemGroup>
30+
<ProjectReference Include="..\..\src\Injectio.Attributes\Injectio.Attributes.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="true" />
31+
<ProjectReference Include="..\..\src\Injectio.Generators\Injectio.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
32+
<ProjectReference Include="..\Injectio.Tests.Library\Injectio.Tests.Library.csproj" />
33+
</ItemGroup>
34+
35+
<ItemGroup>
36+
<Using Include="Xunit" />
37+
</ItemGroup>
38+
39+
</Project>
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
using FluentAssertions;
2+
3+
using Injectio.Tests.Library;
4+
5+
using Microsoft.Extensions.DependencyInjection;
6+
7+
using Xunit.Abstractions;
8+
9+
namespace Injectio.Acceptance.Tests;
10+
11+
[Collection(DependencyInjectionCollection.CollectionName)]
12+
public class LibraryServiceTests(ITestOutputHelper output, DependencyInjectionFixture fixture) : DependencyInjectionBase(output, fixture)
13+
{
14+
[Fact]
15+
public void ShouldResolveService()
16+
{
17+
var service1 = Services.GetService<IService1>();
18+
service1.Should().NotBeNull();
19+
service1.Should().BeOfType<ServiceMultiple>();
20+
}
21+
22+
[Fact]
23+
public void ShouldResolveDuplicateStrategyAppend()
24+
{
25+
var services = Services.GetServices<IService2>();
26+
services.Should().NotBeNull();
27+
services.Count().Should().Be(2);
28+
29+
services.Should().ContainSingle(s => s.GetType() == typeof(ServiceMultiple));
30+
services.Should().ContainSingle(s => s.GetType() == typeof(ScopedWithInterfacesService2));
31+
}
32+
33+
[Fact]
34+
public void ShouldResolveServiceWithFactory()
35+
{
36+
var factoryService1 = Services.GetService<IFactoryService1>();
37+
factoryService1.Should().NotBeNull();
38+
factoryService1.Should().BeOfType<FactoryService1>();
39+
40+
var factoryInstance = factoryService1 as FactoryService1;
41+
factoryInstance.Should().NotBeNull();
42+
43+
var service1 = factoryInstance.Service;
44+
service1.Should().NotBeNull();
45+
service1.Should().BeOfType<ServiceMultiple>();
46+
}
47+
48+
[Fact]
49+
public void ShouldResolveServiceWithModule()
50+
{
51+
var moduleService = Services.GetService<IModuleService>();
52+
moduleService.Should().NotBeNull();
53+
moduleService.Should().BeOfType<ModuleService>();
54+
}
55+
56+
[Fact]
57+
public void ShouldResolveOpenGeneric()
58+
{
59+
var generic = Services.GetService<IOpenGeneric<string>>();
60+
generic.Should().NotBeNull();
61+
generic.Should().BeOfType<OpenGeneric<string>>();
62+
63+
var generic2 = Services.GetService<IOpenGeneric2<string>>();
64+
generic2.Should().NotBeNull();
65+
generic2.Should().BeOfType<OpenGeneric2<string>>();
66+
}
67+
68+
[Fact]
69+
public void ShouldNotResolveTaggedService()
70+
{
71+
var tagService = Services.GetService<IServiceTag>();
72+
tagService.Should().BeNull();
73+
}
74+
75+
[Fact]
76+
public void ShouldResolveKeyedService()
77+
{
78+
var alpaService = Services.GetKeyedService<IServiceKeyed>("Alpha");
79+
alpaService.Should().NotBeNull();
80+
alpaService.Should().BeOfType<ServiceAlphaKeyed>();
81+
82+
var betaService = Services.GetKeyedService<IServiceKeyed>("Beta");
83+
betaService.Should().NotBeNull();
84+
betaService.Should().BeOfType<ServiceBetaKeyed>();
85+
86+
var alpaTypeService = Services.GetKeyedService<IServiceKeyed>(ServiceType.Alpha);
87+
alpaTypeService.Should().NotBeNull();
88+
alpaTypeService.Should().BeOfType<ServiceAlphaTypeKeyed>();
89+
90+
var betaTypeService = Services.GetKeyedService<IServiceKeyed>(ServiceType.Beta);
91+
betaTypeService.Should().NotBeNull();
92+
betaTypeService.Should().BeOfType<ServiceBetaTypeKeyed>();
93+
94+
var charlieService = Services.GetKeyedService<IServiceKeyed>("Charlie");
95+
charlieService.Should().NotBeNull();
96+
charlieService.Should().BeOfType<ServiceFactoryKeyed>();
97+
98+
var charlieInstance = charlieService as ServiceFactoryKeyed;
99+
charlieInstance.Should().NotBeNull();
100+
charlieInstance.ServiceKey.Should().Be("Charlie");
101+
102+
var deltaService = Services.GetKeyedService<IServiceKeyed>("Delta");
103+
deltaService.Should().NotBeNull();
104+
deltaService.Should().BeOfType<ServiceFactoryKeyed>();
105+
106+
var deltaInstance = deltaService as ServiceFactoryKeyed;
107+
deltaInstance.Should().NotBeNull();
108+
deltaInstance.ServiceKey.Should().Be("Delta");
109+
110+
var blahService = Services.GetKeyedService<IServiceKeyed>("Blah");
111+
blahService.Should().BeNull();
112+
}
113+
114+
[Fact]
115+
public void ShouldResolveServiceGeneric()
116+
{
117+
var serviceInterface = Services.GetService<IService<Input, string?>>();
118+
serviceInterface.Should().NotBeNull();
119+
serviceInterface.Should().BeOfType<Service>();
120+
121+
var serviceInstance = Services.GetService<Service>();
122+
serviceInstance.Should().NotBeNull();
123+
124+
serviceInstance.Should().BeSameAs(serviceInterface);
125+
}
126+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using FluentAssertions;
2+
3+
using Injectio.Acceptance.Tests.Services;
4+
5+
using Microsoft.Extensions.DependencyInjection;
6+
7+
using Xunit.Abstractions;
8+
9+
namespace Injectio.Acceptance.Tests;
10+
11+
[Collection(DependencyInjectionCollection.CollectionName)]
12+
public class LocalServiceTests(ITestOutputHelper output, DependencyInjectionFixture fixture) : DependencyInjectionBase(output, fixture)
13+
{
14+
[Fact]
15+
public void ShouldResolveLocalService()
16+
{
17+
var localService = Services.GetRequiredService<ILocalService>();
18+
localService.Should().NotBeNull();
19+
localService.Should().BeOfType<LocalService>();
20+
21+
var localAttributeService = Services.GetRequiredService<ILocalAttributeService>();
22+
localAttributeService.Should().NotBeNull();
23+
localAttributeService.Should().BeOfType<LocalAttributeService>();
24+
}
25+
26+
[Fact]
27+
public void ShouldResolveLocalServiceSameInstance()
28+
{
29+
var localAttributeInstance = Services.GetRequiredService<LocalAttributeService>();
30+
localAttributeInstance.Should().NotBeNull();
31+
localAttributeInstance.Should().BeOfType<LocalAttributeService>();
32+
33+
var localAttributeService = Services.GetRequiredService<ILocalAttributeService>();
34+
localAttributeService.Should().NotBeNull();
35+
localAttributeService.Should().BeOfType<LocalAttributeService>();
36+
37+
localAttributeInstance.Should().BeSameAs(localAttributeService);
38+
}
39+
40+
[Fact]
41+
public void ShouldResolveExplicitService()
42+
{
43+
var localService = Services.GetRequiredService<ILocalAttributeNameService>();
44+
localService.Should().NotBeNull();
45+
localService.Should().BeOfType<LocalAttributeNameService>();
46+
}
47+
48+
[Fact]
49+
public void ShouldCallServiceRegistrationWithTags()
50+
{
51+
// trigger loading of the service registration
52+
var localService = Services.GetRequiredService<ILocalAttributeNameService>();
53+
localService.Should().NotBeNull();
54+
localService.Should().BeOfType<LocalAttributeNameService>();
55+
56+
// check that the tags were set
57+
var tags = ServiceRegistration.Tags;
58+
tags.Should().NotBeNull();
59+
tags.Should().ContainKey(nameof(ServiceRegistration.RegisterWithTagsSet));
60+
tags.Should().ContainKey(nameof(ServiceRegistration.RegisterWithTagsReadOnly));
61+
tags.Should().ContainKey(nameof(ServiceRegistration.RegisterWithTagsCollection));
62+
tags.Should().ContainKey(nameof(ServiceRegistration.RegisterServices));
63+
}
64+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Injectio.Attributes;
2+
using Injectio.Tests.Library;
3+
4+
namespace Injectio.Acceptance.Tests.Services;
5+
6+
public interface ILocalService { }
7+
8+
[RegisterSingleton(Registration = RegistrationStrategy.SelfWithInterfaces, Duplicate = DuplicateStrategy.Replace)]
9+
public class LocalService : ILocalService { }
10+
11+
public interface ILocalAttributeService { }
12+
13+
[RegisterSingleton]
14+
public class LocalAttributeService : ILocalAttributeService, IService1 { }
15+
16+
public interface ILocalAttributeNameService { }
17+
18+
[RegisterSingleton<ILocalAttributeNameService, LocalAttributeNameService>]
19+
public class LocalAttributeNameService : ILocalAttributeNameService, ILocalAttributeService { }

0 commit comments

Comments
 (0)