-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #26 from Jason-eCargo/master
Add generic collection types for AutoSubstitute
- Loading branch information
Showing
3 changed files
with
176 additions
and
10 deletions.
There are no files selected for viewing
153 changes: 153 additions & 0 deletions
153
AutofacContrib.NSubstitute.Tests/AutoSubstituteCollectionFixture.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Security.Cryptography.X509Certificates; | ||
using NSubstitute; | ||
using NUnit.Framework; | ||
|
||
namespace AutofacContrib.NSubstitute.Tests | ||
{ | ||
[TestFixture] | ||
public sealed class AutoSubstituteCollectionFixture | ||
{ | ||
#region stubs | ||
|
||
public interface IServiceItem | ||
{ | ||
} | ||
|
||
public class ServiceItemA : IServiceItem | ||
{ | ||
} | ||
|
||
public class ServiceItemB : IServiceItem | ||
{ | ||
} | ||
|
||
public sealed class TestIEnumerableComponent | ||
{ | ||
public readonly IEnumerable<IServiceItem> ServiceItems; | ||
|
||
public TestIEnumerableComponent(IEnumerable<IServiceItem> serviceItems) | ||
{ | ||
ServiceItems = serviceItems; | ||
} | ||
} | ||
|
||
public sealed class TestIListComponent | ||
{ | ||
public readonly IList<IServiceItem> ServiceItems; | ||
|
||
public TestIListComponent(IList<IServiceItem> serviceItems) | ||
{ | ||
ServiceItems = serviceItems; | ||
} | ||
} | ||
|
||
public sealed class TestIReadOnlyCollectionComponent | ||
{ | ||
public readonly IReadOnlyCollection<IServiceItem> ServiceItems; | ||
|
||
public TestIReadOnlyCollectionComponent(IReadOnlyCollection<IServiceItem> serviceItems) | ||
{ | ||
ServiceItems = serviceItems; | ||
} | ||
} | ||
|
||
public sealed class TestICollectionComponent | ||
{ | ||
public readonly ICollection<IServiceItem> ServiceItems; | ||
|
||
public TestICollectionComponent(ICollection<IServiceItem> serviceItems) | ||
{ | ||
ServiceItems = serviceItems; | ||
} | ||
} | ||
|
||
public sealed class TestIReadOnlyListComponent | ||
{ | ||
public readonly IReadOnlyList<IServiceItem> ServiceItems; | ||
|
||
public TestIReadOnlyListComponent(IReadOnlyList<IServiceItem> serviceItems) | ||
{ | ||
ServiceItems = serviceItems; | ||
} | ||
} | ||
|
||
#endregion | ||
|
||
[Test] | ||
public void TestIEnumerableCorrectlyResolves() | ||
{ | ||
using(var autosub = new AutoSubstitute()) | ||
{ | ||
var mockA = autosub.Provide<IServiceItem, ServiceItemA>(); | ||
var mockB = autosub.Provide<IServiceItem, ServiceItemB>(); | ||
var component = autosub.Resolve<TestIEnumerableComponent>(); | ||
|
||
Assert.That(component.ServiceItems, Is.Not.Empty); | ||
Assert.That(component.ServiceItems.Contains(mockA), Is.True); | ||
Assert.That(component.ServiceItems.Contains(mockB), Is.True); | ||
} | ||
} | ||
|
||
[Test] | ||
public void TestIListCorrectlyResolves() | ||
{ | ||
using(var autosub = new AutoSubstitute()) | ||
{ | ||
var mockA = autosub.Provide<IServiceItem, ServiceItemA>(); | ||
var mockB = autosub.Provide<IServiceItem, ServiceItemB>(); | ||
var component = autosub.Resolve<TestIListComponent>(); | ||
|
||
Assert.That(component.ServiceItems, Is.Not.Empty); | ||
Assert.That(component.ServiceItems.Contains(mockA), Is.True); | ||
Assert.That(component.ServiceItems.Contains(mockB), Is.True); | ||
} | ||
} | ||
|
||
[Test] | ||
public void TestIReadOnlyCollectionCorrectlyResolves() | ||
{ | ||
using(var autosub = new AutoSubstitute()) | ||
{ | ||
var mockA = autosub.Provide<IServiceItem, ServiceItemA>(); | ||
var mockB = autosub.Provide<IServiceItem, ServiceItemB>(); | ||
var component = autosub.Resolve<TestIReadOnlyCollectionComponent>(); | ||
|
||
Assert.That(component.ServiceItems, Is.Not.Empty); | ||
Assert.That(component.ServiceItems.Contains(mockA), Is.True); | ||
Assert.That(component.ServiceItems.Contains(mockB), Is.True); | ||
} | ||
} | ||
|
||
[Test] | ||
public void TestICollectionCorrectlyResolves() | ||
{ | ||
using(var autosub = new AutoSubstitute()) | ||
{ | ||
var mockA = autosub.Provide<IServiceItem, ServiceItemA>(); | ||
var mockB = autosub.Provide<IServiceItem, ServiceItemB>(); | ||
var component = autosub.Resolve<TestICollectionComponent>(); | ||
|
||
Assert.That(component.ServiceItems, Is.Not.Empty); | ||
Assert.That(component.ServiceItems.Contains(mockA), Is.True); | ||
Assert.That(component.ServiceItems.Contains(mockB), Is.True); | ||
} | ||
} | ||
|
||
[Test] | ||
public void TestIReadOnlyListCorrectlyResolves() | ||
{ | ||
using(var autosub = new AutoSubstitute()) | ||
{ | ||
var mockA = autosub.Provide<IServiceItem, ServiceItemA>(); | ||
var mockB = autosub.Provide<IServiceItem, ServiceItemB>(); | ||
var component = autosub.Resolve<TestIReadOnlyListComponent>(); | ||
|
||
Assert.That(component.ServiceItems, Is.Not.Empty); | ||
Assert.That(component.ServiceItems.Contains(mockA), Is.True); | ||
Assert.That(component.ServiceItems.Contains(mockB), Is.True); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 22 additions & 10 deletions
32
AutofacContrib.NSubstitute/NSubstituteRegistrationHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,51 +1,63 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Linq; | ||
using Autofac; | ||
using Autofac.Builder; | ||
using Autofac.Core; | ||
using Autofac.Features.Indexed; | ||
using NSubstitute; | ||
|
||
namespace AutofacContrib.NSubstitute | ||
{ | ||
/// <summary> Resolves unknown interfaces and Mocks using the <see cref="Substitute"/>. </summary> | ||
/// <summary> Resolves unknown interfaces and Mocks using the <see cref="Substitute" />. </summary> | ||
internal class NSubstituteRegistrationHandler : IRegistrationSource | ||
{ | ||
private static readonly IReadOnlyCollection<Type> GenericCollectionTypes = new List<Type> | ||
{ | ||
typeof(IEnumerable<>), | ||
typeof(IList<>), | ||
typeof(IReadOnlyCollection<>), | ||
typeof(ICollection<>), | ||
typeof(IReadOnlyList<>) | ||
}; | ||
|
||
/// <summary> | ||
/// Retrieve a registration for an unregistered service, to be used | ||
/// by the container. | ||
/// Retrieve a registration for an unregistered service, to be used | ||
/// by the container. | ||
/// </summary> | ||
/// <param name="service">The service that was requested.</param> | ||
/// <param name="registrationAccessor"></param> | ||
/// <returns> | ||
/// Registrations for the service. | ||
/// Registrations for the service. | ||
/// </returns> | ||
public IEnumerable<IComponentRegistration> RegistrationsFor | ||
(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor) | ||
{ | ||
if (service == null) | ||
throw new ArgumentNullException("service"); | ||
|
||
var typedService = service as IServiceWithType; | ||
if (typedService == null || | ||
!typedService.ServiceType.IsInterface || | ||
typedService.ServiceType.IsGenericType && typedService.ServiceType.GetGenericTypeDefinition() == typeof(IEnumerable<>) || | ||
IsGenericListOrCollectionInterface(typedService.ServiceType) || | ||
typedService.ServiceType.IsArray || | ||
typeof(IStartable).IsAssignableFrom(typedService.ServiceType)) | ||
return Enumerable.Empty<IComponentRegistration>(); | ||
|
||
var rb = RegistrationBuilder.ForDelegate((c, p) => Substitute.For(new[] { typedService.ServiceType }, null)) | ||
var rb = RegistrationBuilder.ForDelegate((c, p) => Substitute.For(new[] {typedService.ServiceType}, null)) | ||
.As(service) | ||
.InstancePerLifetimeScope(); | ||
|
||
return new[] { rb.CreateRegistration() }; | ||
return new[] {rb.CreateRegistration()}; | ||
} | ||
|
||
public bool IsAdapterForIndividualComponents | ||
{ | ||
get { return false; } | ||
} | ||
|
||
private static bool IsGenericListOrCollectionInterface(Type serviceType) | ||
{ | ||
return serviceType.IsGenericType && GenericCollectionTypes.Contains(serviceType.GetGenericTypeDefinition()); | ||
} | ||
} | ||
} |