Skip to content

Commit dfec133

Browse files
committed
Improve testing
1 parent 5b6da55 commit dfec133

File tree

4 files changed

+128
-31
lines changed

4 files changed

+128
-31
lines changed

src/Futurum.WebApiEndpoint.Micro/FormFileWithPayload.cs

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,28 +23,37 @@ public class FormFileWithPayload<TPayload> : IBindableFromHttpContext<FormFileWi
2323

2424
var form = await context.Request.ReadFormAsync();
2525

26-
var payloadStringValues = form[nameof(Payload).ToLower()].ToString();
27-
var payload = JsonSerializer.Deserialize<TPayload>(payloadStringValues, jsonOptions);
26+
var payload = GetPayload(form, jsonOptions);
2827

29-
if (payload == null)
30-
{
31-
throw new JsonException($"Failed to deserialize {nameof(Payload).ToLower()}: '{payloadStringValues}' as type '{typeof(TPayload).Name}'");
32-
}
28+
var file = GetFile(form);
3329

34-
if (!form.Files.Any())
30+
return payload != null && file != null
31+
? new FormFileWithPayload<TPayload>
32+
{
33+
Payload = payload,
34+
File = file
35+
}
36+
: null;
37+
}
38+
39+
private static TPayload? GetPayload(IFormCollection form, JsonSerializerOptions jsonOptions)
40+
{
41+
if (form.TryGetValue(nameof(Payload).ToLower(), out var payloadStringValues))
3542
{
36-
throw new InvalidOperationException("No file found in request");
37-
}
43+
var payloadString = payloadStringValues.ToString();
44+
var payload = JsonSerializer.Deserialize<TPayload>(payloadString, jsonOptions);
3845

39-
var file = form.Files.Single();
46+
return payload;
47+
}
4048

41-
return new FormFileWithPayload<TPayload>
42-
{
43-
Payload = payload,
44-
File = file
45-
};
49+
return default;
4650
}
4751

52+
private static IFormFile? GetFile(IFormCollection form) =>
53+
!form.Files.Any()
54+
? default
55+
: form.Files.Single();
56+
4857
public static void PopulateMetadata(ParameterInfo parameter, EndpointBuilder builder)
4958
{
5059
builder.Metadata.Add(new ConsumesAttribute(typeof(FormFileWithPayload<TPayload>), "multipart/form-data"));

src/Futurum.WebApiEndpoint.Micro/FormFilesWithPayload.cs

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,37 @@ public class FormFilesWithPayload<TPayload> : IBindableFromHttpContext<FormFiles
2323

2424
var form = await context.Request.ReadFormAsync();
2525

26-
var payloadStringValues = form[nameof(Payload).ToLower()].ToString();
27-
var payload = JsonSerializer.Deserialize<TPayload>(payloadStringValues, jsonOptions);
26+
var payload = GetPayload(form, jsonOptions);
2827

29-
if (payload == null)
30-
{
31-
throw new JsonException($"Failed to deserialize {nameof(Payload).ToLower()}: '{payloadStringValues}' as type '{typeof(TPayload).Name}'");
32-
}
28+
var files = GetFiles(form);
3329

34-
var files = form.Files;
30+
return payload != null && files != null
31+
? new FormFilesWithPayload<TPayload>
32+
{
33+
Payload = payload,
34+
Files = files
35+
}
36+
: null;
37+
}
3538

36-
return new FormFilesWithPayload<TPayload>
39+
private static TPayload? GetPayload(IFormCollection form, JsonSerializerOptions jsonOptions)
40+
{
41+
if (form.TryGetValue(nameof(Payload).ToLower(), out var payloadStringValues))
3742
{
38-
Payload = payload,
39-
Files = files
40-
};
43+
var payloadString = payloadStringValues.ToString();
44+
var payload = JsonSerializer.Deserialize<TPayload>(payloadString, jsonOptions);
45+
46+
return payload;
47+
}
48+
49+
return default;
4150
}
4251

52+
private static IFormFileCollection? GetFiles(IFormCollection form) =>
53+
!form.Files.Any()
54+
? null
55+
: form.Files;
56+
4357
public static void PopulateMetadata(ParameterInfo parameter, EndpointBuilder builder)
4458
{
4559
builder.Metadata.Add(new ConsumesAttribute(typeof(FormFilesWithPayload<TPayload>), "multipart/form-data"));

test/Futurum.WebApiEndpoint.Micro.Tests/FormFileWithPayloadTests.cs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ namespace Futurum.WebApiEndpoint.Micro.Tests;
1111
public class FormFileWithPayloadTests
1212
{
1313
[Fact]
14-
public async Task check()
14+
public async Task success()
1515
{
1616
await using var fileStream = File.OpenRead("./Data/hello-world.txt");
1717

1818
var formFile = new FormFile(fileStream, 0, fileStream.Length, "hello-world.txt", "hello-world.txt");
1919

2020
var id = Guid.NewGuid().ToString();
2121
var payload = new PayloadDto(id);
22-
22+
2323
var payloadJson = JsonSerializer.Serialize(payload, new JsonSerializerOptions(JsonSerializerDefaults.Web));
2424

2525
var httpContext = new DefaultHttpContext();
@@ -39,5 +39,42 @@ public async Task check()
3939
result.Payload.Name.Should().Be(id);
4040
}
4141

42+
[Fact]
43+
public async Task when_Payload_missing_return_null()
44+
{
45+
await using var fileStream = File.OpenRead("./Data/hello-world.txt");
46+
47+
var formFile = new FormFile(fileStream, 0, fileStream.Length, "hello-world.txt", "hello-world.txt");
48+
49+
var httpContext = new DefaultHttpContext();
50+
httpContext.Request.Form = new FormCollection(new Dictionary<string, StringValues>(), new FormFileCollection { formFile });
51+
52+
var services = new ServiceCollection();
53+
httpContext.RequestServices = services.BuildServiceProvider();
54+
55+
var result = await FormFileWithPayload<PayloadDto>.BindAsync(httpContext, null);
56+
57+
result.Should().BeNull();
58+
}
59+
60+
[Fact]
61+
public async Task when_File_missing_return_null()
62+
{
63+
var id = Guid.NewGuid().ToString();
64+
var payload = new PayloadDto(id);
65+
66+
var payloadJson = JsonSerializer.Serialize(payload, new JsonSerializerOptions(JsonSerializerDefaults.Web));
67+
68+
var httpContext = new DefaultHttpContext();
69+
httpContext.Request.Form = new FormCollection(new Dictionary<string, StringValues> { { "payload", payloadJson } }, new FormFileCollection());
70+
71+
var services = new ServiceCollection();
72+
httpContext.RequestServices = services.BuildServiceProvider();
73+
74+
var result = await FormFileWithPayload<PayloadDto>.BindAsync(httpContext, null);
75+
76+
result.Should().BeNull();
77+
}
78+
4279
public record PayloadDto(string Name);
4380
}

test/Futurum.WebApiEndpoint.Micro.Tests/FormFilesWithPayloadTests.cs

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public async Task check()
1919

2020
var id = Guid.NewGuid().ToString();
2121
var payload = new PayloadDto(id);
22-
22+
2323
var payloadJson = JsonSerializer.Serialize(payload, new JsonSerializerOptions(JsonSerializerDefaults.Web));
2424

2525
var httpContext = new DefaultHttpContext();
@@ -33,17 +33,54 @@ public async Task check()
3333
result.Should().NotBeNull();
3434

3535
result.Files.Count.Should().Be(2);
36-
36+
3737
result.Files.First().Name.Should().Be("hello-world.txt");
3838
result.Files.First().FileName.Should().Be("hello-world.txt");
3939
result.Files.First().Length.Should().Be(fileStream.Length);
40-
40+
4141
result.Files.Skip(1).First().Name.Should().Be("hello-world.txt");
4242
result.Files.Skip(1).First().FileName.Should().Be("hello-world.txt");
4343
result.Files.Skip(1).First().Length.Should().Be(fileStream.Length);
4444

4545
result.Payload.Name.Should().Be(id);
4646
}
4747

48+
[Fact]
49+
public async Task when_Payload_missing_return_null()
50+
{
51+
await using var fileStream = File.OpenRead("./Data/hello-world.txt");
52+
53+
var formFile = new FormFile(fileStream, 0, fileStream.Length, "hello-world.txt", "hello-world.txt");
54+
55+
var httpContext = new DefaultHttpContext();
56+
httpContext.Request.Form = new FormCollection(new Dictionary<string, StringValues>(), new FormFileCollection { formFile, formFile });
57+
58+
var services = new ServiceCollection();
59+
httpContext.RequestServices = services.BuildServiceProvider();
60+
61+
var result = await FormFilesWithPayload<PayloadDto>.BindAsync(httpContext, null);
62+
63+
result.Should().BeNull();
64+
}
65+
66+
[Fact]
67+
public async Task when_File_missing_return_null()
68+
{
69+
var id = Guid.NewGuid().ToString();
70+
var payload = new PayloadDto(id);
71+
72+
var payloadJson = JsonSerializer.Serialize(payload, new JsonSerializerOptions(JsonSerializerDefaults.Web));
73+
74+
var httpContext = new DefaultHttpContext();
75+
httpContext.Request.Form = new FormCollection(new Dictionary<string, StringValues> { { "payload", payloadJson } }, new FormFileCollection());
76+
77+
var services = new ServiceCollection();
78+
httpContext.RequestServices = services.BuildServiceProvider();
79+
80+
var result = await FormFilesWithPayload<PayloadDto>.BindAsync(httpContext, null);
81+
82+
result.Should().BeNull();
83+
}
84+
4885
public record PayloadDto(string Name);
4986
}

0 commit comments

Comments
 (0)