Skip to content

Commit 859370f

Browse files
authored
Merge pull request #26 from Jason-eCargo/master
Add generic collection types for AutoSubstitute
2 parents 27d9e62 + f258cd8 commit 859370f

File tree

3 files changed

+176
-10
lines changed

3 files changed

+176
-10
lines changed
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Security.Cryptography.X509Certificates;
4+
using NSubstitute;
5+
using NUnit.Framework;
6+
7+
namespace AutofacContrib.NSubstitute.Tests
8+
{
9+
[TestFixture]
10+
public sealed class AutoSubstituteCollectionFixture
11+
{
12+
#region stubs
13+
14+
public interface IServiceItem
15+
{
16+
}
17+
18+
public class ServiceItemA : IServiceItem
19+
{
20+
}
21+
22+
public class ServiceItemB : IServiceItem
23+
{
24+
}
25+
26+
public sealed class TestIEnumerableComponent
27+
{
28+
public readonly IEnumerable<IServiceItem> ServiceItems;
29+
30+
public TestIEnumerableComponent(IEnumerable<IServiceItem> serviceItems)
31+
{
32+
ServiceItems = serviceItems;
33+
}
34+
}
35+
36+
public sealed class TestIListComponent
37+
{
38+
public readonly IList<IServiceItem> ServiceItems;
39+
40+
public TestIListComponent(IList<IServiceItem> serviceItems)
41+
{
42+
ServiceItems = serviceItems;
43+
}
44+
}
45+
46+
public sealed class TestIReadOnlyCollectionComponent
47+
{
48+
public readonly IReadOnlyCollection<IServiceItem> ServiceItems;
49+
50+
public TestIReadOnlyCollectionComponent(IReadOnlyCollection<IServiceItem> serviceItems)
51+
{
52+
ServiceItems = serviceItems;
53+
}
54+
}
55+
56+
public sealed class TestICollectionComponent
57+
{
58+
public readonly ICollection<IServiceItem> ServiceItems;
59+
60+
public TestICollectionComponent(ICollection<IServiceItem> serviceItems)
61+
{
62+
ServiceItems = serviceItems;
63+
}
64+
}
65+
66+
public sealed class TestIReadOnlyListComponent
67+
{
68+
public readonly IReadOnlyList<IServiceItem> ServiceItems;
69+
70+
public TestIReadOnlyListComponent(IReadOnlyList<IServiceItem> serviceItems)
71+
{
72+
ServiceItems = serviceItems;
73+
}
74+
}
75+
76+
#endregion
77+
78+
[Test]
79+
public void TestIEnumerableCorrectlyResolves()
80+
{
81+
using(var autosub = new AutoSubstitute())
82+
{
83+
var mockA = autosub.Provide<IServiceItem, ServiceItemA>();
84+
var mockB = autosub.Provide<IServiceItem, ServiceItemB>();
85+
var component = autosub.Resolve<TestIEnumerableComponent>();
86+
87+
Assert.That(component.ServiceItems, Is.Not.Empty);
88+
Assert.That(component.ServiceItems.Contains(mockA), Is.True);
89+
Assert.That(component.ServiceItems.Contains(mockB), Is.True);
90+
}
91+
}
92+
93+
[Test]
94+
public void TestIListCorrectlyResolves()
95+
{
96+
using(var autosub = new AutoSubstitute())
97+
{
98+
var mockA = autosub.Provide<IServiceItem, ServiceItemA>();
99+
var mockB = autosub.Provide<IServiceItem, ServiceItemB>();
100+
var component = autosub.Resolve<TestIListComponent>();
101+
102+
Assert.That(component.ServiceItems, Is.Not.Empty);
103+
Assert.That(component.ServiceItems.Contains(mockA), Is.True);
104+
Assert.That(component.ServiceItems.Contains(mockB), Is.True);
105+
}
106+
}
107+
108+
[Test]
109+
public void TestIReadOnlyCollectionCorrectlyResolves()
110+
{
111+
using(var autosub = new AutoSubstitute())
112+
{
113+
var mockA = autosub.Provide<IServiceItem, ServiceItemA>();
114+
var mockB = autosub.Provide<IServiceItem, ServiceItemB>();
115+
var component = autosub.Resolve<TestIReadOnlyCollectionComponent>();
116+
117+
Assert.That(component.ServiceItems, Is.Not.Empty);
118+
Assert.That(component.ServiceItems.Contains(mockA), Is.True);
119+
Assert.That(component.ServiceItems.Contains(mockB), Is.True);
120+
}
121+
}
122+
123+
[Test]
124+
public void TestICollectionCorrectlyResolves()
125+
{
126+
using(var autosub = new AutoSubstitute())
127+
{
128+
var mockA = autosub.Provide<IServiceItem, ServiceItemA>();
129+
var mockB = autosub.Provide<IServiceItem, ServiceItemB>();
130+
var component = autosub.Resolve<TestICollectionComponent>();
131+
132+
Assert.That(component.ServiceItems, Is.Not.Empty);
133+
Assert.That(component.ServiceItems.Contains(mockA), Is.True);
134+
Assert.That(component.ServiceItems.Contains(mockB), Is.True);
135+
}
136+
}
137+
138+
[Test]
139+
public void TestIReadOnlyListCorrectlyResolves()
140+
{
141+
using(var autosub = new AutoSubstitute())
142+
{
143+
var mockA = autosub.Provide<IServiceItem, ServiceItemA>();
144+
var mockB = autosub.Provide<IServiceItem, ServiceItemB>();
145+
var component = autosub.Resolve<TestIReadOnlyListComponent>();
146+
147+
Assert.That(component.ServiceItems, Is.Not.Empty);
148+
Assert.That(component.ServiceItems.Contains(mockA), Is.True);
149+
Assert.That(component.ServiceItems.Contains(mockB), Is.True);
150+
}
151+
}
152+
}
153+
}

AutofacContrib.NSubstitute.Tests/AutofacContrib.NSubstitute.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
<Reference Include="System.Xml" />
5757
</ItemGroup>
5858
<ItemGroup>
59+
<Compile Include="AutoSubstituteCollectionFixture.cs" />
5960
<Compile Include="AutoSubstituteFixture.cs" />
6061
<Compile Include="KeyedRegistrationFixture.cs" />
6162
<Compile Include="Properties\AssemblyInfo.cs" />
Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,63 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Diagnostics;
43
using System.Linq;
54
using Autofac;
65
using Autofac.Builder;
76
using Autofac.Core;
8-
using Autofac.Features.Indexed;
97
using NSubstitute;
108

119
namespace AutofacContrib.NSubstitute
1210
{
13-
/// <summary> Resolves unknown interfaces and Mocks using the <see cref="Substitute"/>. </summary>
11+
/// <summary> Resolves unknown interfaces and Mocks using the <see cref="Substitute" />. </summary>
1412
internal class NSubstituteRegistrationHandler : IRegistrationSource
1513
{
14+
private static readonly IReadOnlyCollection<Type> GenericCollectionTypes = new List<Type>
15+
{
16+
typeof(IEnumerable<>),
17+
typeof(IList<>),
18+
typeof(IReadOnlyCollection<>),
19+
typeof(ICollection<>),
20+
typeof(IReadOnlyList<>)
21+
};
22+
1623
/// <summary>
17-
/// Retrieve a registration for an unregistered service, to be used
18-
/// by the container.
24+
/// Retrieve a registration for an unregistered service, to be used
25+
/// by the container.
1926
/// </summary>
2027
/// <param name="service">The service that was requested.</param>
2128
/// <param name="registrationAccessor"></param>
2229
/// <returns>
23-
/// Registrations for the service.
30+
/// Registrations for the service.
2431
/// </returns>
2532
public IEnumerable<IComponentRegistration> RegistrationsFor
2633
(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
2734
{
2835
if (service == null)
2936
throw new ArgumentNullException("service");
30-
37+
3138
var typedService = service as IServiceWithType;
3239
if (typedService == null ||
3340
!typedService.ServiceType.IsInterface ||
34-
typedService.ServiceType.IsGenericType && typedService.ServiceType.GetGenericTypeDefinition() == typeof(IEnumerable<>) ||
41+
IsGenericListOrCollectionInterface(typedService.ServiceType) ||
3542
typedService.ServiceType.IsArray ||
3643
typeof(IStartable).IsAssignableFrom(typedService.ServiceType))
3744
return Enumerable.Empty<IComponentRegistration>();
3845

39-
var rb = RegistrationBuilder.ForDelegate((c, p) => Substitute.For(new[] { typedService.ServiceType }, null))
46+
var rb = RegistrationBuilder.ForDelegate((c, p) => Substitute.For(new[] {typedService.ServiceType}, null))
4047
.As(service)
4148
.InstancePerLifetimeScope();
4249

43-
return new[] { rb.CreateRegistration() };
50+
return new[] {rb.CreateRegistration()};
4451
}
4552

4653
public bool IsAdapterForIndividualComponents
4754
{
4855
get { return false; }
4956
}
57+
58+
private static bool IsGenericListOrCollectionInterface(Type serviceType)
59+
{
60+
return serviceType.IsGenericType && GenericCollectionTypes.Contains(serviceType.GetGenericTypeDefinition());
61+
}
5062
}
5163
}

0 commit comments

Comments
 (0)