Skip to content
This repository was archived by the owner on Jan 24, 2021. It is now read-only.

Commit 041354d

Browse files
committed
Merge pull request #1305 from thecodejunkie/fluent-validation-improvements
Fluent validation improvements
2 parents ae4b443 + 70772b4 commit 041354d

28 files changed

+365
-467
lines changed

Diff for: src/Nancy.Demo.Validation/Models/Product.cs

+59-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
namespace Nancy.Demo.Validation.Models
22
{
3+
using System;
4+
using System.Collections.Generic;
35
using FluentValidation;
6+
using FluentValidation.Internal;
7+
using FluentValidation.Validators;
8+
using Nancy.Validation;
9+
using Nancy.Validation.FluentValidation;
410

511
public class Product
612
{
@@ -14,7 +20,7 @@ public class ProductValidator : AbstractValidator<Product>
1420
public ProductValidator()
1521
{
1622
RuleFor(product => product.Name).NotEmpty();
17-
RuleFor(product => product.Name).Length(1, 10);
23+
RuleFor(product => product.Name).Length(1, 10).OddLength();
1824
RuleFor(product => product.Name).Matches("[A-Z]*");
1925
RuleFor(product => product.Name).EmailAddress();
2026

@@ -23,4 +29,56 @@ public ProductValidator()
2329
RuleFor(product => product.Price).Equal(5);
2430
}
2531
}
32+
33+
public class OddLengthStringValidator : PropertyValidator
34+
{
35+
public OddLengthStringValidator()
36+
: base("'{PropertyName}' has to be of odd length.")
37+
{
38+
}
39+
40+
protected override bool IsValid(PropertyValidatorContext context)
41+
{
42+
var value =
43+
context.PropertyValue as string;
44+
45+
if (value == null)
46+
{
47+
return false;
48+
}
49+
50+
return (value.Length % 2 != 0);
51+
}
52+
}
53+
54+
public static class FluentValidationExtensions
55+
{
56+
public static IRuleBuilderOptions<T, string> OddLength<T>(this IRuleBuilder<T, string> ruleBuilder)
57+
{
58+
return ruleBuilder.SetValidator(new OddLengthStringValidator());
59+
}
60+
}
61+
62+
public class OddLengthStringValidatorAdapter : AdapterBase
63+
{
64+
public override bool CanHandle(IPropertyValidator validator)
65+
{
66+
return validator is OddLengthStringValidator;
67+
}
68+
69+
public override IEnumerable<ModelValidationRule> GetRules(PropertyRule rule, IPropertyValidator validator)
70+
{
71+
yield return new OddLengthStringRule(
72+
base.FormatMessage(rule, validator),
73+
base.GetMemberNames(rule));
74+
}
75+
}
76+
77+
public class OddLengthStringRule : ModelValidationRule
78+
{
79+
public OddLengthStringRule(Func<string, string> errorMessageFormatter, IEnumerable<string> memberNames)
80+
: base("OddLengthString", errorMessageFormatter, memberNames)
81+
{
82+
}
83+
}
2684
}

Diff for: src/Nancy.Validation.FluentValidation.Tests/DefaultFluentAdapterFactoryFixture.cs

+25-168
Original file line numberDiff line numberDiff line change
@@ -3,213 +3,70 @@ namespace Nancy.Validation.FluentValidation.Tests
33
using FakeItEasy;
44
using Nancy.Tests;
55
using Xunit;
6-
using global::FluentValidation.Internal;
76
using global::FluentValidation.Validators;
87

98
public class DefaultFluentAdapterFactoryFixture
109
{
11-
private PropertyRule rule;
12-
private DefaultFluentAdapterFactory factory;
13-
14-
public DefaultFluentAdapterFactoryFixture()
15-
{
16-
this.rule = new PropertyRule(null, null, null, null, null, null);
17-
this.factory = new DefaultFluentAdapterFactory();
18-
}
19-
2010
[Fact]
21-
public void Should_create_custom_adapter_for_unknown_validator()
11+
public void Should_return_adapter_that_can_handle_validator()
2212
{
2313
// Given
2414
var validator = A.Fake<IPropertyValidator>();
2515

26-
// When
27-
var result = factory.Create(this.rule, validator);
16+
var adapter1 = A.Fake<IFluentAdapter>();
17+
A.CallTo(() => adapter1.CanHandle(A<IPropertyValidator>._)).Returns(false);
2818

29-
// Then
30-
result.ShouldBeOfType<FluentAdapter>();
31-
}
19+
var adapter2 = A.Fake<IFluentAdapter>();
20+
A.CallTo(() => adapter2.CanHandle(A<IPropertyValidator>._)).Returns(true);
3221

33-
[Fact]
34-
public void Should_create_emailadapter_for_emailvalidator()
35-
{
36-
// Given
37-
var validator = new EmailValidator();
22+
var factory = CreateFactory(adapter1, adapter2);
3823

3924
// When
40-
var result = factory.Create(this.rule, validator);
25+
var result = factory.Create(validator);
4126

4227
// Then
43-
result.ShouldBeOfType<EmailAdapter>();
28+
result.ShouldBeSameAs(adapter2);
4429
}
4530

4631
[Fact]
47-
public void Should_create_equaladapter_for_equalvalidator()
32+
public void Should_pass_validator_to_canhandle_method_on_adapter()
4833
{
49-
// Given
50-
var validator = new EqualValidator(10);
51-
52-
// When
53-
var result = factory.Create(this.rule, validator);
54-
55-
// Then
56-
result.ShouldBeOfType<EqualAdapter>();
57-
}
58-
59-
[Fact]
60-
public void Should_create_exactlengthadapter_for_exactlengthvalidator()
61-
{
62-
// Given
63-
var validator = new ExactLengthValidator(10);
64-
65-
// When
66-
var result = factory.Create(this.rule, validator);
67-
68-
// Then
69-
result.ShouldBeOfType<ExactLengthAdapater>();
70-
}
71-
72-
[Fact]
73-
public void Should_create_exclusivebetweenadapter_for_exclusivebetweenvalidator()
74-
{
75-
// Given
76-
var validator = new ExclusiveBetweenValidator(1, 10);
77-
78-
// When
79-
var result = factory.Create(this.rule, validator);
80-
81-
// Then
82-
result.ShouldBeOfType<ExclusiveBetweenAdapter>();
83-
}
84-
85-
[Fact]
86-
public void Should_create_greaterthanadapter_for_greaterthanvalidator()
87-
{
88-
// Given
89-
var validator = new GreaterThanValidator(1);
90-
91-
// When
92-
var result = factory.Create(this.rule, validator);
93-
94-
// Then
95-
result.ShouldBeOfType<GreaterThanAdapter>();
96-
}
97-
98-
[Fact]
99-
public void Should_create_greaterthanorequaladapter_for_greaterthanorequalvalidator()
100-
{
101-
// Given
102-
var validator = new GreaterThanOrEqualValidator(1);
103-
104-
// When
105-
var result = factory.Create(this.rule, validator);
106-
107-
// Then
108-
result.ShouldBeOfType<GreaterThanOrEqualAdapter>();
109-
}
110-
111-
[Fact]
112-
public void Should_create_inclusivebetweenadapter_for_inclusivebetweenvalidator()
113-
{
114-
// Given
115-
var validator = new InclusiveBetweenValidator(1, 10);
116-
117-
// When
118-
var result = factory.Create(this.rule, validator);
119-
120-
// Then
121-
result.ShouldBeOfType<InclusiveBetweenAdapter>();
122-
}
123-
124-
[Fact]
125-
public void Should_create_lengthadapter_for_lengthvalidator()
126-
{
127-
// Given
128-
var validator = new LengthValidator(1, 10);
129-
130-
// When
131-
var result = factory.Create(this.rule, validator);
132-
133-
// Then
134-
result.ShouldBeOfType<LengthAdapter>();
135-
}
136-
137-
[Fact]
138-
public void Should_create_lessthanadapter_for_lessthanvalidator()
139-
{
140-
// Given
141-
var validator = new LessThanValidator(1);
142-
143-
// When
144-
var result = factory.Create(this.rule, validator);
145-
146-
// Then
147-
result.ShouldBeOfType<LessThanAdapter>();
148-
}
149-
150-
[Fact]
151-
public void Should_create_lessthanorequaladapter_for_lessthanorequalvalidator()
152-
{
153-
// Given
154-
var validator = new LessThanOrEqualValidator(1);
155-
156-
// When
157-
var result = factory.Create(this.rule, validator);
158-
159-
// Then
160-
result.ShouldBeOfType<LessThanOrEqualAdapter>();
161-
}
34+
var validator = A.Fake<IPropertyValidator>();
35+
var adapter = A.Fake<IFluentAdapter>();
16236

163-
[Fact]
164-
public void Should_create_notemptyadapter_for_notemptyvalidator()
165-
{
166-
// Given
167-
var validator = new NotEmptyValidator(1);
37+
var factory = CreateFactory(adapter);
16838

16939
// When
170-
var result = factory.Create(this.rule, validator);
40+
factory.Create(validator);
17141

17242
// Then
173-
result.ShouldBeOfType<NotEmptyAdapter>();
43+
A.CallTo(() => adapter.CanHandle(validator)).MustHaveHappened();
17444
}
17545

17646
[Fact]
177-
public void Should_create_notequaladapter_for_notequalvalidator()
47+
public void Should_return_fallback_adapter_when_no_other_adapter_can_handle_validator()
17848
{
17949
// Given
180-
var validator = new NotEqualValidator(1);
50+
var validator = A.Fake<IPropertyValidator>();
18151

182-
// When
183-
var result = factory.Create(this.rule, validator);
52+
var adapter1 = A.Fake<IFluentAdapter>();
53+
A.CallTo(() => adapter1.CanHandle(A<IPropertyValidator>._)).Returns(false);
18454

185-
// Then
186-
result.ShouldBeOfType<NotEqualAdapter>();
187-
}
55+
var adapter2 = A.Fake<IFluentAdapter>();
56+
A.CallTo(() => adapter2.CanHandle(A<IPropertyValidator>._)).Returns(false);
18857

189-
[Fact]
190-
public void Should_create_notnulladapter_for_notnullvalidator()
191-
{
192-
// Given
193-
var validator = new NotNullValidator();
58+
var factory = CreateFactory(adapter1, adapter2);
19459

19560
// When
196-
var result = factory.Create(this.rule, validator);
61+
var result = factory.Create(validator);
19762

19863
// Then
199-
result.ShouldBeOfType<NotNullAdapter>();
64+
result.ShouldBeOfType<FallbackAdapter>();
20065
}
20166

202-
[Fact]
203-
public void Should_create_regularexpressionadapter_for_regularexpressionvalidator()
67+
private static DefaultFluentAdapterFactory CreateFactory(params IFluentAdapter[] adapters)
20468
{
205-
// Given
206-
var validator = new RegularExpressionValidator("[A-Z]*");
207-
208-
// When
209-
var result = factory.Create(this.rule, validator);
210-
211-
// Then
212-
result.ShouldBeOfType<RegularExpressionAdapter>();
69+
return new DefaultFluentAdapterFactory(adapters);
21370
}
21471
}
21572
}

Diff for: src/Nancy.Validation.FluentValidation.Tests/FluentValidationValidatorFactoryFixture.cs

+20-6
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,26 @@
77

88
public class FluentValidationValidatorFactoryFixture
99
{
10+
private readonly FluentValidationValidatorFactory factory;
11+
12+
public FluentValidationValidatorFactoryFixture()
13+
{
14+
var adapterFactory =
15+
A.Fake<IFluentAdapterFactory>();
16+
17+
var validators =
18+
new IValidator[] {new ClassUnderTestValidator(), new NeverBeUsedTestValidator()};
19+
20+
this.factory =
21+
new FluentValidationValidatorFactory(adapterFactory, validators);
22+
}
23+
1024
[Fact]
1125
public void Should_return_instance_when_validator_was_found_for_type()
1226
{
1327
// Given
14-
var factory = new FluentValidationValidatorFactory(A.Fake<IFluentAdapterFactory>());
15-
1628
// When
17-
var instance = factory.Create(typeof(ClassUnderTest));
29+
var instance = this.factory.Create(typeof(ClassUnderTest));
1830

1931
// Then
2032
instance.ShouldNotBeNull();
@@ -24,10 +36,8 @@ public void Should_return_instance_when_validator_was_found_for_type()
2436
public void Should_return_null_when_no_validator_was_found_for_type()
2537
{
2638
// Given
27-
var factory = new FluentValidationValidatorFactory(A.Fake<IFluentAdapterFactory>());
28-
2939
// When
30-
var instance = factory.Create(typeof(string));
40+
var instance = this.factory.Create(typeof(string));
3141

3242
// Then
3343
instance.ShouldBeNull();
@@ -40,5 +50,9 @@ public class ClassUnderTest
4050
public class ClassUnderTestValidator : AbstractValidator<ClassUnderTest>
4151
{
4252
}
53+
54+
public class NeverBeUsedTestValidator : AbstractValidator<int>
55+
{
56+
}
4357
}
4458
}

Diff for: src/Nancy.Validation.FluentValidation.Tests/Nancy.Validation.FluentValidation.Tests.csproj

-9
Original file line numberDiff line numberDiff line change
@@ -90,19 +90,10 @@
9090
</Reference>
9191
<Reference Include="System" />
9292
<Reference Include="System.Core" />
93-
<Reference Include="System.Xml.Linq" />
94-
<Reference Include="System.Data.DataSetExtensions" />
95-
<Reference Include="Microsoft.CSharp" />
96-
<Reference Include="System.Data" />
97-
<Reference Include="System.Xml" />
9893
<Reference Include="xunit, Version=1.9.1.1600, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
9994
<SpecificVersion>False</SpecificVersion>
10095
<HintPath>..\packages\xunit.1.9.1\lib\net20\xunit.dll</HintPath>
10196
</Reference>
102-
<Reference Include="xunit.extensions, Version=1.9.1.1600, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
103-
<SpecificVersion>False</SpecificVersion>
104-
<HintPath>..\packages\xunit.extensions.1.9.1\lib\net20\xunit.extensions.dll</HintPath>
105-
</Reference>
10697
</ItemGroup>
10798
<ItemGroup>
10899
<Compile Include="..\Nancy.Tests\ShouldExtensions.cs">

0 commit comments

Comments
 (0)