@@ -101,6 +101,111 @@ public async Task TestOnActionExecutionAsync()
101
101
Assert . Contains ( validationFailuresValues [ 2 ] . First ( ) , badRequestObjectResultValidationProblemDetails . Errors [ nameof ( TestModel . Parameter3 ) ] [ 0 ] ) ;
102
102
}
103
103
104
+ [ Fact ]
105
+ public async Task OnActionExecutionAsync_WithInstanceTypeDifferentThanParameterType_UsesInstanceTypeValidator ( )
106
+ {
107
+ // Arrange
108
+ var httpContext = Substitute . For < HttpContext > ( ) ;
109
+ var modelStateDictionary = new ModelStateDictionary ( ) ;
110
+
111
+ var validationFailures = new Dictionary < string , string [ ] >
112
+ {
113
+ { nameof ( CreatePersonRequest . Name ) , [ $ "'{ nameof ( CreatePersonRequest . Name ) } ' must be equal to 'John Doe'."] }
114
+ } ;
115
+ var validationProblemDetails = new ValidationProblemDetails ( validationFailures ) ;
116
+
117
+ var problemDetailsFactory = Substitute . For < ProblemDetailsFactory > ( ) ;
118
+ problemDetailsFactory . CreateValidationProblemDetails ( httpContext , modelStateDictionary ) . Returns ( validationProblemDetails ) ;
119
+
120
+ var serviceProvider = Substitute . For < IServiceProvider > ( ) ;
121
+ serviceProvider . GetService ( typeof ( IValidator < > ) . MakeGenericType ( typeof ( CreateAnimalRequest ) ) ) . Returns ( new CreateAnimalRequestValidator ( ) ) ;
122
+ serviceProvider . GetService ( typeof ( IValidator < > ) . MakeGenericType ( typeof ( CreatePersonRequest ) ) ) . Returns ( new CreatePersonRequestValidator ( ) ) ;
123
+ serviceProvider . GetService ( typeof ( ProblemDetailsFactory ) ) . Returns ( problemDetailsFactory ) ;
124
+
125
+ httpContext . RequestServices . Returns ( serviceProvider ) ;
126
+
127
+ var controller = Substitute . For < AnimalsController > ( ) ;
128
+ var controllerActionDescriptor = new ControllerActionDescriptor
129
+ {
130
+ Parameters =
131
+ [
132
+ new ( )
133
+ {
134
+ Name = "request" ,
135
+ ParameterType = typeof ( CreateAnimalRequest ) ,
136
+ BindingInfo = new BindingInfo { BindingSource = BindingSource . Body }
137
+ }
138
+ ]
139
+ } ;
140
+ var actionContext = Substitute . For < ActionContext > ( httpContext , Substitute . For < RouteData > ( ) , controllerActionDescriptor , modelStateDictionary ) ;
141
+
142
+ var actionArguments = new Dictionary < string , object ? >
143
+ {
144
+ {
145
+ "request" , new CreatePersonRequest
146
+ {
147
+ Name = "Jane Doe"
148
+ }
149
+ } ,
150
+ } ;
151
+ var actionExecutingContext = Substitute . For < ActionExecutingContext > ( actionContext , new List < IFilterMetadata > ( ) , actionArguments , new object ( ) ) ;
152
+ actionExecutingContext . Controller . Returns ( controller ) ;
153
+ actionExecutingContext . ActionDescriptor = controllerActionDescriptor ;
154
+ actionExecutingContext . ActionArguments . Returns ( actionArguments ) ;
155
+
156
+ var actionExecutedContext = Substitute . For < ActionExecutedContext > ( actionContext , new List < IFilterMetadata > ( ) , new object ( ) ) ;
157
+
158
+ var fluentValidationAutoValidationResultFactory = Substitute . For < IFluentValidationAutoValidationResultFactory > ( ) ;
159
+ fluentValidationAutoValidationResultFactory . CreateActionResult ( actionExecutingContext , validationProblemDetails ) . Returns ( new BadRequestObjectResult ( validationProblemDetails ) ) ;
160
+
161
+ var autoValidationMvcConfiguration = Substitute . For < IOptions < AutoValidationMvcConfiguration > > ( ) ;
162
+ autoValidationMvcConfiguration . Value . Returns ( new AutoValidationMvcConfiguration ( ) ) ;
163
+
164
+ var actionFilter = new FluentValidationAutoValidationActionFilter ( fluentValidationAutoValidationResultFactory , autoValidationMvcConfiguration ) ;
165
+
166
+ // Act
167
+ await actionFilter . OnActionExecutionAsync ( actionExecutingContext , ( ) => Task . FromResult ( actionExecutedContext ) ) ;
168
+
169
+ // Assert
170
+ var modelStateDictionaryValues = modelStateDictionary . Values . ToList ( ) ;
171
+ var validationFailuresValues = validationFailures . Values . ToList ( ) ;
172
+ var badRequestObjectResult = ( BadRequestObjectResult ) actionExecutingContext . Result ! ;
173
+ var badRequestObjectResultValidationProblemDetails = ( ValidationProblemDetails ) badRequestObjectResult . Value ! ;
174
+
175
+ Assert . Contains ( validationFailuresValues [ 0 ] . First ( ) , modelStateDictionaryValues [ 0 ] . Errors . Select ( error => error . ErrorMessage ) ) ;
176
+ Assert . Contains ( validationFailuresValues [ 0 ] . First ( ) , badRequestObjectResultValidationProblemDetails . Errors [ nameof ( CreatePersonRequest . Name ) ] [ 0 ] ) ;
177
+ }
178
+
179
+ public class AnimalsController : ControllerBase
180
+ {
181
+ }
182
+
183
+ public class CreateAnimalRequest
184
+ {
185
+ }
186
+
187
+ public class CreatePersonRequest : CreateAnimalRequest
188
+ {
189
+ public required string Name { get ; set ; }
190
+ }
191
+
192
+ public class CreateAnimalRequestValidator : AbstractValidator < CreateAnimalRequest >
193
+ {
194
+ public CreateAnimalRequestValidator ( )
195
+ {
196
+ }
197
+ }
198
+
199
+ public class CreatePersonRequestValidator : AbstractValidator < CreatePersonRequest >
200
+ {
201
+ public CreatePersonRequestValidator ( )
202
+ {
203
+ this . Include ( new CreateAnimalRequestValidator ( ) ) ;
204
+
205
+ this . RuleFor ( x => x . Name ) . Equal ( "John Doe" ) ;
206
+ }
207
+ }
208
+
104
209
public class TestController : ControllerBase
105
210
{
106
211
}
0 commit comments