Skip to content

Commit 5926680

Browse files
authored
Bugfix & code coverage (#2)
1 parent 45a73e0 commit 5926680

6 files changed

Lines changed: 226 additions & 1 deletion

File tree

src/Binders/ParticlesBinderProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public IModelBinder GetBinder(ModelBinderProviderContext context)
2626
{
2727
var genericArgument = type.GetGenericArguments()[0];
2828

29-
if (_binderTypes.TryGetValue(genericArgument.GetGenericTypeDefinition(), out var genericBinderType))
29+
if (genericArgument.IsGenericType && _binderTypes.TryGetValue(genericArgument.GetGenericTypeDefinition(), out var genericBinderType))
3030
{
3131
Type[] typeArgs = { genericArgument.GetGenericArguments()[0] };
3232
Type binderType = genericBinderType.MakeGenericType(typeArgs);

tests/Panner.AspNetCore.Tests/Panner.AspNetCore.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<ItemGroup>
1010
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
1111
<PackageReference Include="Moq" Version="4.13.1" />
12+
<PackageReference Include="NSubstitute" Version="4.2.1" />
1213
<PackageReference Include="xunit" Version="2.4.0" />
1314
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
1415
<PackageReference Include="coverlet.msbuild" Version="2.7.0">
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
namespace Panner.AspNetCore.Tests
2+
{
3+
using Microsoft.AspNetCore.Mvc.ModelBinding;
4+
using NSubstitute;
5+
using System;
6+
using System.Collections.Generic;
7+
using Xunit;
8+
9+
public class ParticlesBinderProviderWorks
10+
{
11+
public class TestObj { }
12+
13+
private readonly ParticlesBinderProvider ParticlesBinderProvider;
14+
15+
public ParticlesBinderProviderWorks()
16+
{
17+
this.ParticlesBinderProvider = new ParticlesBinderProvider();
18+
}
19+
20+
private ModelBinderProviderContext GetContext(Type modelType)
21+
{
22+
IModelMetadataProvider provider = new EmptyModelMetadataProvider();
23+
ModelBinderProviderContext context = Substitute.For<ModelBinderProviderContext>();
24+
context.Metadata.Returns(provider.GetMetadataForType(modelType));
25+
return context;
26+
}
27+
28+
[InlineData(typeof(IReadOnlyCollection<IFilterParticle<TestObj>>), typeof(FilterParticlesModelBinder<TestObj>))]
29+
[InlineData(typeof(IReadOnlyCollection<ISortParticle<TestObj>>), typeof(SortParticlesModelBinder<TestObj>))]
30+
[Theory]
31+
public void WorksForCorrectTypes(Type input, Type output)
32+
{
33+
Assert.NotNull(this.ParticlesBinderProvider.GetBinder(this.GetContext(input)));
34+
//Missing assert to verify that we're getting the correct model binder.
35+
}
36+
37+
[InlineData(typeof(List<IFilterParticle<TestObj>>))]
38+
[InlineData(typeof(IFilterParticle<TestObj>[]))]
39+
[InlineData(typeof(List<ISortParticle<TestObj>>))]
40+
[InlineData(typeof(ISortParticle<TestObj>[]))]
41+
[InlineData(typeof(IReadOnlyCollection<TestObj>))]
42+
[InlineData(typeof(TestObj))]
43+
[InlineData(typeof(int))]
44+
[Theory]
45+
public void ReturnsNullForIncorrectTypes(Type input)
46+
{
47+
Assert.Null(this.ParticlesBinderProvider.GetBinder(this.GetContext(input)));
48+
}
49+
50+
[Fact]
51+
public void ThrowsOnNullContext()
52+
{
53+
Assert.Throws<ArgumentNullException>(() =>
54+
{
55+
this.ParticlesBinderProvider.GetBinder(null);
56+
});
57+
}
58+
}
59+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
namespace Panner.AspNetCore.Tests
2+
{
3+
using Microsoft.AspNetCore.Mvc.ModelBinding;
4+
using NSubstitute;
5+
using System;
6+
using System.Collections;
7+
using System.Linq;
8+
using System.Threading.Tasks;
9+
using Xunit;
10+
11+
public abstract class ParticlesModelBinderWorks<TBinder>
12+
where TBinder : IModelBinder
13+
{
14+
abstract protected TBinder Create(IPContext context);
15+
16+
public ParticlesModelBinderWorks(){}
17+
18+
private IPContext GetPannerContext()
19+
=> Substitute.For<IPContext>();
20+
21+
private ModelBindingContext GetBindingContext(string modelName)
22+
{
23+
var bindingContext = Substitute.For<ModelBindingContext>();
24+
var valueProvider = Substitute.For<IValueProvider>();
25+
var modelStateDict = Substitute.For<ModelStateDictionary>();
26+
27+
bindingContext.ModelName.Returns(modelName);
28+
bindingContext.ValueProvider.Returns(valueProvider);
29+
bindingContext.ModelState.Returns(modelStateDict);
30+
31+
return bindingContext;
32+
}
33+
34+
[Fact]
35+
public void NullIPContextThrows()
36+
{
37+
Assert.Throws<ArgumentNullException>(() =>
38+
{
39+
var x = Create(null);
40+
});
41+
}
42+
43+
[Fact]
44+
public void NullBindingContextThrows()
45+
{
46+
var x = Create(GetPannerContext());
47+
48+
Assert.Throws<ArgumentNullException>(() =>
49+
{
50+
x.BindModelAsync(null);
51+
});
52+
}
53+
54+
[Fact]
55+
public async Task EmptyEnumerableIfNotFoundInBindingContextAsync()
56+
{
57+
var modelName = Guid.NewGuid().ToString();
58+
var bindingContext = GetBindingContext(modelName);
59+
60+
bindingContext.ValueProvider.GetValue(modelName).Returns(ValueProviderResult.None);
61+
62+
var x = Create(GetPannerContext());
63+
await x.BindModelAsync(bindingContext);
64+
65+
Assert.True(bindingContext.Result.IsModelSet);
66+
Assert.Empty((IEnumerable)bindingContext.Result.Model);
67+
}
68+
69+
[Fact]
70+
public async Task FailsIfTheInputCantBeParsedByTheContext()
71+
{
72+
var modelName = Guid.NewGuid().ToString();
73+
var valueResult = Guid.NewGuid().ToString();
74+
75+
var bindingContext = GetBindingContext(modelName);
76+
bindingContext.ValueProvider.GetValue(modelName).Returns(new ValueProviderResult(valueResult));
77+
78+
var x = Create(GetPannerContext());
79+
await x.BindModelAsync(bindingContext);
80+
81+
Assert.False(bindingContext.Result.IsModelSet);
82+
Assert.False(bindingContext.ModelState.IsValid);
83+
Assert.True(bindingContext.ModelState.ContainsKey(modelName));
84+
Assert.Equal(1, bindingContext.ModelState.ErrorCount);
85+
Assert.Contains("Could not parse provided", bindingContext.ModelState[modelName].Errors.Single().ErrorMessage);
86+
}
87+
88+
}
89+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
namespace Panner.AspNetCore.Tests
2+
{
3+
public class TestObj
4+
{ }
5+
6+
public class SortParticlesModelBinderWorks : ParticlesModelBinderWorks<SortParticlesModelBinder<TestObj>>
7+
{
8+
// All tests are in the generic ParticlesModelBinderWorks class.
9+
// This class only provides construction of the specific model binder.
10+
protected override SortParticlesModelBinder<TestObj> Create(IPContext context)
11+
{
12+
return new SortParticlesModelBinder<TestObj>(context);
13+
}
14+
}
15+
16+
public class FilterParticlesModelBinderWorks : ParticlesModelBinderWorks<FilterParticlesModelBinder<TestObj>>
17+
{
18+
// All tests are in the generic ParticlesModelBinderWorks class.
19+
// This class only provides construction of the specific model binder.
20+
protected override FilterParticlesModelBinder<TestObj> Create(IPContext context)
21+
{
22+
return new FilterParticlesModelBinder<TestObj>(context);
23+
}
24+
}
25+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
namespace Panner.AspNetCore.Tests
2+
{
3+
using Microsoft.AspNetCore.Mvc;
4+
using Microsoft.Extensions.DependencyInjection;
5+
using Microsoft.Extensions.Options;
6+
using Panner.Builders;
7+
using System;
8+
using System.Linq;
9+
using Xunit;
10+
11+
public class UsePannerWorks
12+
{
13+
public IServiceProvider GetServiceProvider(Action<PContextBuilder> configuration)
14+
=> new ServiceCollection()
15+
.UsePanner(configuration)
16+
.BuildServiceProvider();
17+
18+
[Fact]
19+
public void AddsContextToServiceProvider()
20+
{
21+
var x = GetServiceProvider(x => { });
22+
Assert.NotNull(x);
23+
}
24+
25+
[Fact]
26+
public void AddsBinderProvider()
27+
{
28+
var mvcOptions = GetServiceProvider(x => { })
29+
.GetService<IOptions<MvcOptions>>();
30+
31+
Assert.NotNull(mvcOptions);
32+
33+
var foundProvider = mvcOptions.Value.ModelBinderProviders
34+
.Any(x => x.GetType() == typeof(ParticlesBinderProvider));
35+
36+
Assert.True(foundProvider);
37+
}
38+
39+
[Fact]
40+
public void ConfigurationExecutes()
41+
{
42+
var executed = false;
43+
44+
var mvcOptions = GetServiceProvider(x => {
45+
executed = true;
46+
});
47+
48+
Assert.True(executed);
49+
}
50+
}
51+
}

0 commit comments

Comments
 (0)