Skip to content

Commit 050d5c3

Browse files
author
Bart Koelman
authored
Added tests for blobs (#1125)
1 parent 8f49b64 commit 050d5c3

File tree

4 files changed

+309
-0
lines changed

4 files changed

+309
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using JetBrains.Annotations;
2+
using Microsoft.EntityFrameworkCore;
3+
4+
namespace JsonApiDotNetCoreTests.IntegrationTests.Blobs;
5+
6+
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
7+
public sealed class BlobDbContext : DbContext
8+
{
9+
public DbSet<ImageContainer> ImageContainers => Set<ImageContainer>();
10+
11+
public BlobDbContext(DbContextOptions<BlobDbContext> options)
12+
: base(options)
13+
{
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Bogus;
2+
using TestBuildingBlocks;
3+
4+
// @formatter:wrap_chained_method_calls chop_always
5+
// @formatter:keep_existing_linebreaks true
6+
7+
namespace JsonApiDotNetCoreTests.IntegrationTests.Blobs;
8+
9+
internal sealed class BlobFakers : FakerContainer
10+
{
11+
private readonly Lazy<Faker<ImageContainer>> _lazyImageContainerFaker = new(() =>
12+
new Faker<ImageContainer>()
13+
.UseSeed(GetFakerSeed())
14+
.RuleFor(imageContainer => imageContainer.FileName, faker => faker.System.FileName())
15+
.RuleFor(imageContainer => imageContainer.Data, faker => faker.Random.Bytes(128))
16+
.RuleFor(imageContainer => imageContainer.Thumbnail, faker => faker.Random.Bytes(64)));
17+
18+
public Faker<ImageContainer> ImageContainer => _lazyImageContainerFaker.Value;
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
using System.Net;
2+
using FluentAssertions;
3+
using JsonApiDotNetCore.Resources;
4+
using JsonApiDotNetCore.Serialization.Objects;
5+
using Microsoft.Extensions.DependencyInjection;
6+
using TestBuildingBlocks;
7+
using Xunit;
8+
9+
namespace JsonApiDotNetCoreTests.IntegrationTests.Blobs;
10+
11+
public sealed class BlobTests : IClassFixture<IntegrationTestContext<TestableStartup<BlobDbContext>, BlobDbContext>>
12+
{
13+
private readonly IntegrationTestContext<TestableStartup<BlobDbContext>, BlobDbContext> _testContext;
14+
private readonly BlobFakers _fakers = new();
15+
16+
public BlobTests(IntegrationTestContext<TestableStartup<BlobDbContext>, BlobDbContext> testContext)
17+
{
18+
_testContext = testContext;
19+
20+
testContext.UseController<ImageContainersController>();
21+
22+
testContext.ConfigureServicesAfterStartup(services =>
23+
{
24+
services.AddScoped(typeof(IResourceChangeTracker<>), typeof(NeverSameResourceChangeTracker<>));
25+
});
26+
}
27+
28+
[Fact]
29+
public async Task Can_get_primary_resource_by_ID()
30+
{
31+
// Arrange
32+
ImageContainer container = _fakers.ImageContainer.Generate();
33+
34+
await _testContext.RunOnDatabaseAsync(async dbContext =>
35+
{
36+
dbContext.ImageContainers.Add(container);
37+
await dbContext.SaveChangesAsync();
38+
});
39+
40+
string route = $"/imageContainers/{container.StringId}";
41+
42+
// Act
43+
(HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecuteGetAsync<Document>(route);
44+
45+
// Assert
46+
httpResponse.Should().HaveStatusCode(HttpStatusCode.OK);
47+
48+
responseDocument.Data.SingleValue.ShouldNotBeNull();
49+
responseDocument.Data.SingleValue.Type.Should().Be("imageContainers");
50+
responseDocument.Data.SingleValue.Id.Should().Be(container.StringId);
51+
responseDocument.Data.SingleValue.Attributes.ShouldContainKey("fileName").With(value => value.Should().Be(container.FileName));
52+
responseDocument.Data.SingleValue.Attributes.ShouldContainKey("data").As<byte[]>().With(value => value.Should().Equal(container.Data));
53+
responseDocument.Data.SingleValue.Attributes.ShouldContainKey("thumbnail").As<byte[]>().With(value => value.Should().Equal(container.Thumbnail));
54+
responseDocument.Data.SingleValue.Relationships.Should().BeNull();
55+
}
56+
57+
[Fact]
58+
public async Task Can_create_resource()
59+
{
60+
// Arrange
61+
ImageContainer newContainer = _fakers.ImageContainer.Generate();
62+
63+
var requestBody = new
64+
{
65+
data = new
66+
{
67+
type = "imageContainers",
68+
attributes = new
69+
{
70+
fileName = newContainer.FileName,
71+
data = Convert.ToBase64String(newContainer.Data),
72+
thumbnail = Convert.ToBase64String(newContainer.Thumbnail!)
73+
}
74+
}
75+
};
76+
77+
const string route = "/imageContainers";
78+
79+
// Act
80+
(HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync<Document>(route, requestBody);
81+
82+
// Assert
83+
httpResponse.Should().HaveStatusCode(HttpStatusCode.Created);
84+
85+
responseDocument.Data.SingleValue.ShouldNotBeNull();
86+
responseDocument.Data.SingleValue.Type.Should().Be("imageContainers");
87+
responseDocument.Data.SingleValue.Attributes.ShouldContainKey("fileName").With(value => value.Should().Be(newContainer.FileName));
88+
responseDocument.Data.SingleValue.Attributes.ShouldContainKey("data").As<byte[]>().With(value => value.Should().Equal(newContainer.Data));
89+
responseDocument.Data.SingleValue.Attributes.ShouldContainKey("thumbnail").As<byte[]>().With(value => value.Should().Equal(newContainer.Thumbnail));
90+
responseDocument.Data.SingleValue.Relationships.Should().BeNull();
91+
92+
long newContainerId = long.Parse(responseDocument.Data.SingleValue.Id.ShouldNotBeNull());
93+
94+
await _testContext.RunOnDatabaseAsync(async dbContext =>
95+
{
96+
ImageContainer containerInDatabase = await dbContext.ImageContainers.FirstWithIdAsync(newContainerId);
97+
98+
containerInDatabase.FileName.Should().Be(newContainer.FileName);
99+
containerInDatabase.Data.Should().Equal(newContainer.Data);
100+
containerInDatabase.Thumbnail.Should().Equal(newContainer.Thumbnail);
101+
});
102+
}
103+
104+
[Fact]
105+
public async Task Can_update_resource()
106+
{
107+
// Arrange
108+
ImageContainer existingContainer = _fakers.ImageContainer.Generate();
109+
110+
byte[] newData = _fakers.ImageContainer.Generate().Data;
111+
byte[] newThumbnail = _fakers.ImageContainer.Generate().Thumbnail!;
112+
113+
await _testContext.RunOnDatabaseAsync(async dbContext =>
114+
{
115+
dbContext.ImageContainers.Add(existingContainer);
116+
await dbContext.SaveChangesAsync();
117+
});
118+
119+
var requestBody = new
120+
{
121+
data = new
122+
{
123+
type = "imageContainers",
124+
id = existingContainer.StringId,
125+
attributes = new
126+
{
127+
data = Convert.ToBase64String(newData),
128+
thumbnail = Convert.ToBase64String(newThumbnail)
129+
}
130+
}
131+
};
132+
133+
string route = $"/imageContainers/{existingContainer.StringId}";
134+
135+
// Act
136+
(HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePatchAsync<Document>(route, requestBody);
137+
138+
// Assert
139+
httpResponse.Should().HaveStatusCode(HttpStatusCode.OK);
140+
141+
responseDocument.Data.SingleValue.ShouldNotBeNull();
142+
responseDocument.Data.SingleValue.Type.Should().Be("imageContainers");
143+
responseDocument.Data.SingleValue.Id.Should().Be(existingContainer.StringId);
144+
responseDocument.Data.SingleValue.Attributes.ShouldContainKey("fileName").With(value => value.Should().Be(existingContainer.FileName));
145+
responseDocument.Data.SingleValue.Attributes.ShouldContainKey("data").As<byte[]>().With(value => value.Should().Equal(newData));
146+
responseDocument.Data.SingleValue.Attributes.ShouldContainKey("thumbnail").As<byte[]>().With(value => value.Should().Equal(newThumbnail));
147+
responseDocument.Data.SingleValue.Relationships.Should().BeNull();
148+
149+
await _testContext.RunOnDatabaseAsync(async dbContext =>
150+
{
151+
ImageContainer containerInDatabase = await dbContext.ImageContainers.FirstWithIdAsync(existingContainer.Id);
152+
153+
containerInDatabase.FileName.Should().Be(existingContainer.FileName);
154+
containerInDatabase.Data.Should().Equal(newData);
155+
containerInDatabase.Thumbnail.Should().Equal(newThumbnail);
156+
});
157+
}
158+
159+
[Fact]
160+
public async Task Can_update_resource_with_empty_blob()
161+
{
162+
// Arrange
163+
ImageContainer existingContainer = _fakers.ImageContainer.Generate();
164+
165+
await _testContext.RunOnDatabaseAsync(async dbContext =>
166+
{
167+
dbContext.ImageContainers.Add(existingContainer);
168+
await dbContext.SaveChangesAsync();
169+
});
170+
171+
var requestBody = new
172+
{
173+
data = new
174+
{
175+
type = "imageContainers",
176+
id = existingContainer.StringId,
177+
attributes = new
178+
{
179+
data = string.Empty
180+
}
181+
}
182+
};
183+
184+
string route = $"/imageContainers/{existingContainer.StringId}";
185+
186+
// Act
187+
(HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePatchAsync<Document>(route, requestBody);
188+
189+
// Assert
190+
httpResponse.Should().HaveStatusCode(HttpStatusCode.OK);
191+
192+
responseDocument.Data.SingleValue.ShouldNotBeNull();
193+
responseDocument.Data.SingleValue.Type.Should().Be("imageContainers");
194+
responseDocument.Data.SingleValue.Id.Should().Be(existingContainer.StringId);
195+
responseDocument.Data.SingleValue.Attributes.ShouldContainKey("fileName").With(value => value.Should().Be(existingContainer.FileName));
196+
responseDocument.Data.SingleValue.Attributes.ShouldContainKey("data").As<byte[]>().With(value => value.Should().BeEmpty());
197+
responseDocument.Data.SingleValue.Relationships.Should().BeNull();
198+
199+
await _testContext.RunOnDatabaseAsync(async dbContext =>
200+
{
201+
ImageContainer containerInDatabase = await dbContext.ImageContainers.FirstWithIdAsync(existingContainer.Id);
202+
203+
containerInDatabase.FileName.Should().Be(existingContainer.FileName);
204+
containerInDatabase.Data.Should().BeEmpty();
205+
});
206+
}
207+
208+
[Fact]
209+
public async Task Can_update_resource_with_null_blob()
210+
{
211+
// Arrange
212+
ImageContainer existingContainer = _fakers.ImageContainer.Generate();
213+
214+
await _testContext.RunOnDatabaseAsync(async dbContext =>
215+
{
216+
dbContext.ImageContainers.Add(existingContainer);
217+
await dbContext.SaveChangesAsync();
218+
});
219+
220+
var requestBody = new
221+
{
222+
data = new
223+
{
224+
type = "imageContainers",
225+
id = existingContainer.StringId,
226+
attributes = new
227+
{
228+
thumbnail = (object?)null
229+
}
230+
}
231+
};
232+
233+
string route = $"/imageContainers/{existingContainer.StringId}";
234+
235+
// Act
236+
(HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePatchAsync<Document>(route, requestBody);
237+
238+
// Assert
239+
httpResponse.Should().HaveStatusCode(HttpStatusCode.OK);
240+
241+
responseDocument.Data.SingleValue.ShouldNotBeNull();
242+
responseDocument.Data.SingleValue.Type.Should().Be("imageContainers");
243+
responseDocument.Data.SingleValue.Id.Should().Be(existingContainer.StringId);
244+
responseDocument.Data.SingleValue.Attributes.ShouldContainKey("fileName").With(value => value.Should().Be(existingContainer.FileName));
245+
responseDocument.Data.SingleValue.Attributes.ShouldContainKey("thumbnail").With(value => value.Should().BeNull());
246+
responseDocument.Data.SingleValue.Relationships.Should().BeNull();
247+
248+
await _testContext.RunOnDatabaseAsync(async dbContext =>
249+
{
250+
ImageContainer containerInDatabase = await dbContext.ImageContainers.FirstWithIdAsync(existingContainer.Id);
251+
252+
containerInDatabase.FileName.Should().Be(existingContainer.FileName);
253+
containerInDatabase.Thumbnail.Should().BeNull();
254+
});
255+
}
256+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using JetBrains.Annotations;
2+
using JsonApiDotNetCore.Resources;
3+
using JsonApiDotNetCore.Resources.Annotations;
4+
5+
namespace JsonApiDotNetCoreTests.IntegrationTests.Blobs;
6+
7+
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
8+
[Resource(ControllerNamespace = "JsonApiDotNetCoreTests.IntegrationTests.Blobs")]
9+
public sealed class ImageContainer : Identifiable<long>
10+
{
11+
[Attr]
12+
public string FileName { get; set; } = null!;
13+
14+
[Attr]
15+
public byte[] Data { get; set; } = Array.Empty<byte>();
16+
17+
[Attr]
18+
public byte[]? Thumbnail { get; set; }
19+
}

0 commit comments

Comments
 (0)