- add: Unit tests

This commit is contained in:
2025-07-03 12:17:15 +03:00
parent 517fadaab8
commit ae17ff2d89
15 changed files with 467 additions and 12 deletions

View File

@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.6" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="NUnit" Version="3.14.0"/>
<PackageReference Include="NUnit.Analyzers" Version="3.9.0"/>
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
</ItemGroup>
<ItemGroup>
<Using Include="NUnit.Framework"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Nebula.Packager\Nebula.Packager.csproj" />
<ProjectReference Include="..\Nebula.Shared\Nebula.Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,16 @@
using Microsoft.Extensions.DependencyInjection;
namespace Nebula.UnitTest.NebulaSharedTests;
public abstract class BaseSharedTest
{
protected SharedUnit _sharedUnit = default!;
public abstract void BeforeServiceBuild(IServiceCollection services);
public virtual void Setup()
{
_sharedUnit = TestServiceHelper.GetSharedUnit(BeforeServiceBuild);
}
}

View File

@@ -0,0 +1,90 @@
using Microsoft.Extensions.DependencyInjection;
using Nebula.Shared.Services;
namespace Nebula.UnitTest.NebulaSharedTests;
[TestFixture]
[TestOf(typeof(ConfigurationService))]
public sealed class ConfigurationServiceTests: BaseSharedTest
{
private ConfigurationService _conVarService;
public override void BeforeServiceBuild(IServiceCollection services)
{
TestServiceHelper.InitFileServiceTest();
}
[SetUp]
public override void Setup()
{
base.Setup();
_conVarService = _sharedUnit.GetService<ConfigurationService>();
}
[Test]
public void GetDefaultConVarTest()
{
var value = _conVarService.GetConfigValue(TestConVar.SimpleConvar);
Assert.NotNull(value);
Assert.That(value, Is.EqualTo(TestConVar.SimpleConvar.DefaultValue));
}
[Test]
public void GetNullConVarTest()
{
var value = _conVarService.GetConfigValue(TestConVar.NullConvar);
Assert.Null(value);
}
[Test]
public void WriteConVarTest()
{
var value = _conVarService.GetConfigValue(TestConVar.SimpleConvar);
Assert.That(value, Is.EqualTo(TestConVar.SimpleConvar.DefaultValue));
_conVarService.SetConfigValue(TestConVar.SimpleConvar, "notdefault");
value = _conVarService.GetConfigValue(TestConVar.SimpleConvar);
Assert.That(value, Is.Not.EqualTo(TestConVar.SimpleConvar.DefaultValue));
Assert.That(value, Is.EqualTo("notdefault"));
_conVarService.SetConfigValue(TestConVar.SimpleConvar, null);
value = _conVarService.GetConfigValue(TestConVar.SimpleConvar);
Assert.That(value, Is.EqualTo(TestConVar.SimpleConvar.DefaultValue));
}
[Test]
public void WriteComplexConvarTest()
{
var testVar = new TestVarObject("Alex", 2);
_conVarService.SetConfigValue(TestConVar.TestVarObject, testVar);
var value = _conVarService.GetConfigValue(TestConVar.TestVarObject);
Assert.That(value, Is.EqualTo(testVar));
_conVarService.SetConfigValue(TestConVar.TestVarObject, default);
}
[Test]
public void WriteArrayConvarTest()
{
var testVarArr = new[] { new TestVarObject("Alex", 2), new TestVarObject("Vitya", 3) };
_conVarService.SetConfigValue(TestConVar.TestVarArray, testVarArr);
var value = _conVarService.GetConfigValue(TestConVar.TestVarArray);
Assert.NotNull(value);
Assert.That(testVarArr.SequenceEqual(value));
_conVarService.SetConfigValue(TestConVar.TestVarArray, null);
}
}
public static class TestConVar
{
public static ConVar<string> SimpleConvar = ConVarBuilder.Build("test.convarsimple", "test");
public static ConVar<string?> NullConvar = ConVarBuilder.Build<string?>("test.convarsimplenull");
public static ConVar<TestVarObject> TestVarObject = ConVarBuilder.Build<TestVarObject>("test.convarobject", default);
public static ConVar<TestVarObject[]> TestVarArray = ConVarBuilder.Build<TestVarObject[]>("test.convarobject.array");
}
public record struct TestVarObject(string Name, int Count);

View File

@@ -0,0 +1,123 @@
using System.IO.Compression;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Nebula.Shared.Models;
using Nebula.Shared.Services;
using Robust.LoaderApi;
namespace Nebula.UnitTest.NebulaSharedTests;
[TestFixture]
[TestOf(typeof(FileService))]
public class FileServiceTests : BaseSharedTest
{
private FileService _fileService = default!;
public override void BeforeServiceBuild(IServiceCollection services)
{
TestServiceHelper.InitFileServiceTest();
}
[SetUp]
public override void Setup()
{
base.Setup();
_fileService = _sharedUnit.GetService<FileService>();
}
[Test]
public void CreateFileApi_CreatesCorrectPath()
{
var subPath = "test-folder";
var fileApi = _fileService.CreateFileApi(subPath);
using (var stream = new MemoryStream("test"u8.ToArray()))
{
fileApi.Save("test.txt", stream);
}
var expectedPath = Path.Combine(FileService.RootPath, subPath);
Assert.That(Directory.Exists(expectedPath), Is.True, $"Expected path to be created: {expectedPath}");
}
[Test]
public void EnsureTempDir_CreatesDirectoryAndReturnsApi()
{
var api = _fileService.EnsureTempDir(out var path);
Assert.That(Directory.Exists(path), Is.True);
Assert.That(api, Is.Not.Null);
}
[Test]
public void OpenZip_ReturnsZipFileApi_WhenValid()
{
var testZipPath = Path.Combine(FileService.RootPath, "test.zip");
using (var archive = ZipFile.Open(testZipPath, ZipArchiveMode.Create))
{
var entry = archive.CreateEntry("test.txt");
using var streamWriter = new StreamWriter(entry.Open());
streamWriter.Write(testZipPath);
streamWriter.Flush();
}
IDisposable? streamDisposable = null;
var mockFileApi = new Mock<IFileApi>();
mockFileApi
.Setup(x => x.TryOpen(testZipPath, out It.Ref<Stream>.IsAny))
.Returns((string _, out Stream stream) =>
{
stream = File.OpenRead(testZipPath);
streamDisposable = stream;
return true;
});
var zipApi = _fileService.OpenZip(testZipPath, mockFileApi.Object);
Assert.That(zipApi, Is.Not.Null);
Assert.That(zipApi.TryOpen("test.txt", out var textStream), Is.True);
using (var reader = new StreamReader(textStream!))
{
Assert.That(reader.ReadToEnd(), Is.EqualTo(testZipPath));
}
textStream!.Dispose();
streamDisposable?.Dispose();
File.Delete(testZipPath);
}
[Test]
public void RemoveAllFiles_DeletesAllFilesAndDirectories()
{
var testDir = Path.Combine(FileService.RootPath, "cleanup-test");
Directory.CreateDirectory(testDir);
File.WriteAllText(Path.Combine(testDir, "test1.txt"), "data");
Directory.CreateDirectory(Path.Combine(testDir, "subdir"));
var mockHandler = new Mock<ILoadingHandler>();
mockHandler.Setup(x => x.AppendJob(It.IsAny<int>())).Verifiable();
mockHandler.Setup(x => x.AppendResolvedJob(It.IsAny<int>())).Verifiable();
_fileService.RemoveAllFiles("cleanup-test", mockHandler.Object, CancellationToken.None);
Assert.That(Directory.Exists(testDir), Is.True);
Assert.That(Directory.GetFiles(testDir).Length, Is.EqualTo(0));
Assert.That(Directory.GetDirectories(testDir).Length, Is.EqualTo(0));
}
[Test]
public void OpenZip_ThrowsException_WhenFileApiFails()
{
var mockFileApi = new Mock<IFileApi>();
mockFileApi.Setup(x => x.TryOpen(It.IsAny<string>(), out It.Ref<Stream>.IsAny))
.Returns(false);
var result = _fileService.OpenZip("invalid.zip", mockFileApi.Object);
Assert.That(result, Is.Null);
}
}

View File

@@ -0,0 +1,42 @@
using Microsoft.Extensions.DependencyInjection;
using Nebula.Shared.Services;
namespace Nebula.UnitTest.NebulaSharedTests;
[TestFixture]
[TestOf(nameof(PopupMessageService))]
public class PopupMessageServiceTests : BaseSharedTest
{
public override void BeforeServiceBuild(IServiceCollection services)
{
}
[SetUp]
public override void Setup()
{
base.Setup();
var popupService = _sharedUnit.GetService<PopupMessageService>();
popupService.OnCloseRequired = (popup) => ((IDisposable)popup).Dispose();
}
[Test]
public void DisposeTest()
{
var popup = new TestPopup();
var popupService = _sharedUnit.GetService<PopupMessageService>();
popupService.ClosePopup(popup);
Assert.That(popup.Disposed, Is.True);
}
private sealed class TestPopup : IDisposable
{
public bool Disposed { get; private set; }
public void Dispose()
{
Disposed = true;
}
}
}

View File

@@ -0,0 +1,77 @@
using System.Net;
using System.Text;
using System.Text.Json;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Moq.Protected;
using Nebula.Shared.Services;
namespace Nebula.UnitTest.NebulaSharedTests;
[TestFixture]
[TestOf(typeof(RestService))]
public class RestServiceTests : BaseSharedTest
{
public static readonly TestDto ExpectedObject = new()
{
Id = 1,
Name = "Test",
};
public static string ObjectString => JsonSerializer.Serialize(ExpectedObject, SerializerOptions);
public static readonly JsonSerializerOptions SerializerOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
public override void BeforeServiceBuild(IServiceCollection services)
{
var mockHandler = new Mock<HttpMessageHandler>();
mockHandler
.Protected()
.Setup<Task<HttpResponseMessage>>("SendAsync",
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(ObjectString, Encoding.UTF8, "application/json")
});
var client = new HttpClient(mockHandler.Object);
services.AddSingleton(client);
}
[SetUp]
public override void Setup()
{
base.Setup();
}
[Test]
public async Task GetTest()
{
var restService = _sharedUnit.GetService<RestService>();
var result = await restService.GetAsync<TestDto>(new Uri("http://localhost/test"), CancellationToken.None);
Assert.NotNull(result);
Assert.That(result.Id, Is.EqualTo(ExpectedObject.Id));
Assert.That(result.Name, Is.EqualTo(ExpectedObject.Name));
}
[Test]
public async Task PostTest()
{
var restService = _sharedUnit.GetService<RestService>();
var result = await restService.PostAsync<TestDto, TestDto>(ExpectedObject,new Uri("http://localhost/test"), CancellationToken.None);
Assert.NotNull(result);
Assert.That(result.Id, Is.EqualTo(ExpectedObject.Id));
Assert.That(result.Name, Is.EqualTo(ExpectedObject.Name));
}
public class TestDto
{
public int Id { get; set; }
public string Name { get; set; }
}
}

View File

@@ -0,0 +1,46 @@
using Microsoft.Extensions.DependencyInjection;
using Nebula.Shared;
using Nebula.Shared.Services;
namespace Nebula.UnitTest;
public static class TestServiceHelper
{
public static SharedUnit GetSharedUnit(Action<IServiceCollection> beforeServiceBuild)
{
var services = new ServiceCollection();
beforeServiceBuild.Invoke(services);
services.AddServices();
var serviceProvider = services.BuildServiceProvider();
return new SharedUnit(serviceProvider);
}
public static void InitFileServiceTest()
{
var path = Path.Combine(Path.GetTempPath(), "tempThink"+Path.GetRandomFileName());
Directory.CreateDirectory(path);
FileService.RootPath = path;
Console.WriteLine("Change root path for file api: " + FileService.RootPath);
}
}
public sealed class LauncherUnit : SharedUnit
{
public LauncherUnit(IServiceProvider serviceProvider) : base(serviceProvider)
{
}
}
public class SharedUnit
{
public SharedUnit(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
}
public IServiceProvider ServiceProvider { get; }
public T GetService<T>() where T : notnull => ServiceProvider.GetRequiredService<T>();
}