132 lines
5.3 KiB
C#
132 lines
5.3 KiB
C#
|
|
using System.Net.Http.Json;
|
|||
|
|
using Microsoft.AspNetCore.Mvc.Testing;
|
|||
|
|
using Microsoft.EntityFrameworkCore;
|
|||
|
|
using Microsoft.Extensions.DependencyInjection;
|
|||
|
|
using OtaFleet.Api.Data;
|
|||
|
|
using OtaFleet.Api.Endpoints;
|
|||
|
|
|
|||
|
|
namespace OtaFleet.Tests;
|
|||
|
|
|
|||
|
|
public class VehicleTests : IClassFixture<WebApplicationFactory<Program>>
|
|||
|
|
{
|
|||
|
|
private readonly WebApplicationFactory<Program> _factory;
|
|||
|
|
|
|||
|
|
public VehicleTests(WebApplicationFactory<Program> factory)
|
|||
|
|
{
|
|||
|
|
_factory = factory.WithWebHostBuilder(builder =>
|
|||
|
|
{
|
|||
|
|
builder.ConfigureServices(services =>
|
|||
|
|
{
|
|||
|
|
var dbContextDescriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<OtaDbContext>));
|
|||
|
|
if (dbContextDescriptor != null) services.Remove(dbContextDescriptor);
|
|||
|
|
|
|||
|
|
var dbConnectionDescriptor = services.SingleOrDefault(d => d.ServiceType == typeof(System.Data.Common.DbConnection));
|
|||
|
|
if (dbConnectionDescriptor != null) services.Remove(dbConnectionDescriptor);
|
|||
|
|
|
|||
|
|
services.AddSingleton<System.Data.Common.DbConnection>(container =>
|
|||
|
|
{
|
|||
|
|
var connection = new Microsoft.Data.Sqlite.SqliteConnection("DataSource=:memory:");
|
|||
|
|
connection.Open();
|
|||
|
|
return connection;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
services.AddDbContext<OtaDbContext>((container, options) =>
|
|||
|
|
{
|
|||
|
|
var connection = container.GetRequiredService<System.Data.Common.DbConnection>();
|
|||
|
|
options.UseSqlite(connection);
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
[Fact]
|
|||
|
|
public async Task Register_ShouldReturnVehicle()
|
|||
|
|
{
|
|||
|
|
var client = _factory.CreateClient();
|
|||
|
|
var request = new RegisterVehicleRequest("TEST_VIN_001", "1.0.0");
|
|||
|
|
|
|||
|
|
var response = await client.PostAsJsonAsync("/api/vehicles/register", request);
|
|||
|
|
|
|||
|
|
response.EnsureSuccessStatusCode();
|
|||
|
|
var vehicle = await response.Content.ReadFromJsonAsync<OtaFleet.Api.Data.Entities.Vehicle>();
|
|||
|
|
Assert.NotNull(vehicle);
|
|||
|
|
Assert.Equal("TEST_VIN_001", vehicle.Vin);
|
|||
|
|
Assert.Equal("Online", vehicle.Status);
|
|||
|
|
}
|
|||
|
|
[Fact]
|
|||
|
|
public async Task GetVehicles_WithGroup_ShouldNotThrowObjectCycle()
|
|||
|
|
{
|
|||
|
|
var client = _factory.CreateClient();
|
|||
|
|
|
|||
|
|
// 1. Create a Group
|
|||
|
|
var groupRes = await client.PostAsJsonAsync("/api/admin/groups", new OtaFleet.Api.Endpoints.CreateGroupRequest("CycleTestGroup", "Testing Cycles"));
|
|||
|
|
groupRes.EnsureSuccessStatusCode();
|
|||
|
|
var group = await groupRes.Content.ReadFromJsonAsync<OtaFleet.Api.Data.Entities.VehicleGroup>();
|
|||
|
|
Assert.NotNull(group);
|
|||
|
|
|
|||
|
|
// 2. Register a Vehicle
|
|||
|
|
await client.PostAsJsonAsync("/api/vehicles/register", new RegisterVehicleRequest("CYCLE_VIN", "1.0"));
|
|||
|
|
|
|||
|
|
// 3. Assign Vehicle to Group (This creates the cycle: Vehicle -> Group -> Vehicles -> Vehicle ...)
|
|||
|
|
await client.PostAsJsonAsync($"/api/admin/groups/{group.Id}/vehicles", new OtaFleet.Api.Endpoints.AssignVehicleRequest("CYCLE_VIN"));
|
|||
|
|
|
|||
|
|
// 4. Fetch Vehicles (Should serialize the cycle safely)
|
|||
|
|
var response = await client.GetAsync("/api/admin/vehicles");
|
|||
|
|
response.EnsureSuccessStatusCode();
|
|||
|
|
|
|||
|
|
var vehicles = await response.Content.ReadFromJsonAsync<List<OtaFleet.Api.Data.Entities.Vehicle>>();
|
|||
|
|
Assert.NotEmpty(vehicles);
|
|||
|
|
var v = vehicles.First(x => x.Vin == "CYCLE_VIN");
|
|||
|
|
Assert.NotNull(v.Group);
|
|||
|
|
}
|
|||
|
|
[Fact]
|
|||
|
|
public async Task GetVehicles_ShouldReturnCorrectCount()
|
|||
|
|
{
|
|||
|
|
var client = _factory.CreateClient();
|
|||
|
|
int vehicleCount = 10;
|
|||
|
|
|
|||
|
|
for (int i = 0; i < vehicleCount; i++)
|
|||
|
|
{
|
|||
|
|
await client.PostAsJsonAsync("/api/vehicles/register", new RegisterVehicleRequest($"MULTI_VIN_{i}", "1.0.0"));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var response = await client.GetAsync("/api/admin/vehicles");
|
|||
|
|
response.EnsureSuccessStatusCode();
|
|||
|
|
var vehicles = await response.Content.ReadFromJsonAsync<List<OtaFleet.Api.Data.Entities.Vehicle>>();
|
|||
|
|
|
|||
|
|
Assert.NotNull(vehicles);
|
|||
|
|
// Note: Other tests might have added vehicles, so we check for at least our count
|
|||
|
|
Assert.True(vehicles.Count >= vehicleCount);
|
|||
|
|
Assert.Contains(vehicles, v => v.Vin == "MULTI_VIN_0");
|
|||
|
|
Assert.Contains(vehicles, v => v.Vin == $"MULTI_VIN_{vehicleCount - 1}");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
[Fact]
|
|||
|
|
public async Task LoadTest_ConcurrentRegistrations()
|
|||
|
|
{
|
|||
|
|
var client = _factory.CreateClient();
|
|||
|
|
int requestCount = 100;
|
|||
|
|
var tasks = new List<Task<HttpResponseMessage>>();
|
|||
|
|
|
|||
|
|
for (int i = 0; i < requestCount; i++)
|
|||
|
|
{
|
|||
|
|
// Capture index for closure
|
|||
|
|
int index = i;
|
|||
|
|
tasks.Add(Task.Run(() => client.PostAsJsonAsync("/api/vehicles/register", new RegisterVehicleRequest($"LOAD_VIN_{index}", "1.0.0"))));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var results = await Task.WhenAll(tasks);
|
|||
|
|
|
|||
|
|
foreach (var result in results)
|
|||
|
|
{
|
|||
|
|
result.EnsureSuccessStatusCode();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var response = await client.GetAsync("/api/admin/vehicles");
|
|||
|
|
var vehicles = await response.Content.ReadFromJsonAsync<List<OtaFleet.Api.Data.Entities.Vehicle>>();
|
|||
|
|
|
|||
|
|
Assert.NotNull(vehicles);
|
|||
|
|
Assert.True(vehicles.Count(v => v.Vin.StartsWith("LOAD_VIN_")) == requestCount);
|
|||
|
|
}
|
|||
|
|
}
|