Add UnitTests and made code testable with DI

This commit is contained in:
2025-11-04 20:27:51 +10:30
parent e5787c9321
commit 17be096ae2
22 changed files with 865 additions and 140 deletions
@@ -0,0 +1,119 @@
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using LibHac.Ncm;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Moq;
using NUnit.Framework;
using TinfoilVibeServer.Models;
using TinfoilVibeServer.Services;
using TinfoilVibeServer.Utilities;
namespace TinfoilVibeServerTest.Tests
{
[TestFixture]
public class SnapshotServiceTests
{
private Mock<ILogger<SnapshotService>> _loggerMock;
private SnapshotService _service;
private Mock<INSPExtractor> _nspExtractorMock;
private Mock<IArchiveHandler> _archiveHander;
private Mock<IOptionsMonitor<SnapshotOptions>> _mockOptions;
private SnapshotOptions _options;
[SetUp]
public void SetUp()
{
_mockOptions = new Mock<IOptionsMonitor<SnapshotOptions>>();
_options = new SnapshotOptions()
{
RomExtensions = [".nsp"],
RootDirectories = ["TestData/ROMS"],
SnapshotFile = "TestData/snapshot.json",
SnapshotBackupFile = "TestData/snapshot.bak"
};
/*// ensure ROM test directory has test files removed
foreach (var file in Directory.GetFiles("TestData/ROMS"))
{
File.Delete(file);
}*/
_mockOptions.Setup(m => m.CurrentValue).Returns(_options);
_loggerMock = new Mock<ILogger<SnapshotService>>();
_archiveHander = new Mock<IArchiveHandler>();
_nspExtractorMock = new Mock<INSPExtractor>();
_nspExtractorMock.Setup(extractor => extractor.ExtractHashFromStream(It.IsAny<Stream>())).Returns("HASH");
_nspExtractorMock.Setup(extractor => extractor.ExtractFromStream(It.IsAny<Stream>())).Returns(
new NcaMetadataWithHash(titleId: "0000000000000000","0000000000000000", version: 1, ContentMetaType.Application, "HASH"));
//Settings.RootDirs = new List<string> { "TestData/Root1", "TestData/Root2" };
_service = new SnapshotService(_mockOptions.Object, _nspExtractorMock.Object, _archiveHander.Object, _loggerMock.Object);
}
[TearDown]
public void TearDown()
{
_service.Dispose();
}
[Test]
public async Task BuildSnapshot_WhenFilesChanged_ShouldPersist()
{
// Arrange
await File.WriteAllTextAsync(_options.SnapshotFile, "[]");
var initialHash = _service.GetSnapshot()?.Hash;
// Add a file to Root1
var newFile = Path.Combine(_options.RootDirectories.First(), "new.nsp");
FileSystemExtensions.EnsureDirectoryExists(Path.GetDirectoryName(newFile));
// Create a new valid NSP file
// copy to temp to touch modified date
foreach (var file in Directory.GetFiles("../../../Data/"))
{
var filename = Path.GetFileName(file);
var destFilename = Path.Combine(Path.GetTempPath(), filename);
File.Copy(file, destFilename, true);
var info = new FileInfo(destFilename)
{
LastWriteTimeUtc = DateTime.UtcNow
};
info.CopyTo(Path.Combine(_options.RootDirectories.First(),filename), true);
}
// Act
_service.SnapshotRebuilt+= (sender, args) =>
{
// Assert
var newHash = _service.GetSnapshot()?.Hash;
Assert.That(newHash, Is.Not.EqualTo(initialHash));
};
Task.Delay(300).Wait();
_loggerMock.Verify(
l => l.Log(
LogLevel.Information,
It.IsAny<EventId>(),
It.Is<It.IsAnyType>((v, t) => v.ToString().Contains("Snapshot rebuilt")),
null,
It.IsAny<Func<It.IsAnyType, Exception, string>>()), Times.Once);
}
[Test]
public async Task BuildSnapshot_NoChange_ShouldNotPersist()
{
// Act
_service.BuildSnapshot();
// Act again snapshot should be identical
_service.BuildSnapshot();
// Assert
_loggerMock.Verify(
l => l.Log(
LogLevel.Information,
It.IsAny<EventId>(),
It.Is<It.IsAnyType>((v, t) => v.ToString().Contains("persisting new snapshot")),
null,
It.IsAny<Func<It.IsAnyType, Exception, string>>()), Times.Never);
}
}
}