8ac593d36f
Backend CI / build-and-test (push) Failing after 14m19s
🚀 Create and publish a Docker image / Detect changes in backend and frontend (push) Failing after 12m5s
Frontend CI / build-and-check (push) Failing after 17m58s
🚀 Create and publish a Docker image / Build & publish frontend image (push) Failing after 10m11s
🚀 Create and publish a Docker image / Build & publish backend image (push) Failing after 11m3s
🚀 Create and publish a Docker image / Update stack on Portainer (push) Failing after 14m58s
92 lines
3.3 KiB
C#
92 lines
3.3 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
using NSubstitute;
|
|
using UniVerse.Application.Interfaces;
|
|
using UniVerse.Domain.Entities;
|
|
using UniVerse.Domain.Enums;
|
|
using UniVerse.Infrastructure.Data;
|
|
using UniVerse.Infrastructure.Services;
|
|
using Xunit;
|
|
|
|
namespace UniVerse.Api.Tests.Reviews;
|
|
|
|
public class LlmAnalysisServiceTests
|
|
{
|
|
[Fact]
|
|
public async Task AnalyzeReviewAsync_SavesParsedAnalysisResult()
|
|
{
|
|
await using var db = CreateDbContext();
|
|
await SeedPendingReviewAsync(db);
|
|
var llm = Substitute.For<ILlmClient>();
|
|
llm.AnalyzeReviewAsync(Arg.Any<string>(), Arg.Any<string>())
|
|
.Returns(new LlmReviewAnalysis(
|
|
0.76,
|
|
"Положительный",
|
|
["lecture structure", "practical examples"],
|
|
true,
|
|
"{\"quality_score\":0.76,\"sentiment\":\"Положительный\"}"));
|
|
var gamification = Substitute.For<IGamificationService>();
|
|
gamification.AwardCoinsAsync(
|
|
Arg.Any<int>(),
|
|
Arg.Any<int>(),
|
|
Arg.Any<CoinTransactionType>(),
|
|
Arg.Any<int?>(),
|
|
Arg.Any<int?>(),
|
|
Arg.Any<string?>())
|
|
.Returns(Task.CompletedTask);
|
|
gamification.CheckAndAwardAchievementsAsync(Arg.Any<int>()).Returns(Task.CompletedTask);
|
|
var service = new LlmAnalysisService(db, llm, gamification, NullLogger<LlmAnalysisService>.Instance);
|
|
|
|
await service.AnalyzeReviewAsync(1);
|
|
|
|
var review = await db.Reviews.SingleAsync(r => r.Id == 1);
|
|
Assert.Equal(ReviewLlmStatus.Analyzed, review.LlmStatus);
|
|
Assert.Equal(ReviewSentiment.Positive, review.Sentiment);
|
|
Assert.Equal(0.76, review.QualityScore);
|
|
Assert.True(review.IsInformative);
|
|
Assert.Equal(["lecture structure", "practical examples"], review.LlmTags!);
|
|
Assert.Equal("{\"quality_score\":0.76,\"sentiment\":\"Положительный\"}", review.LlmRawOutput);
|
|
await gamification.Received(1).AwardCoinsAsync(
|
|
1,
|
|
10,
|
|
CoinTransactionType.ReviewReward,
|
|
1,
|
|
null,
|
|
"Informative review reward");
|
|
}
|
|
|
|
private static async Task SeedPendingReviewAsync(AppDbContext db)
|
|
{
|
|
db.Users.Add(new User { Id = 1, Email = "student@test.local", DisplayName = "Student" });
|
|
db.Courses.Add(new Course { Id = 1, Name = "Course" });
|
|
db.Lectures.Add(new Lecture
|
|
{
|
|
Id = 1,
|
|
CourseId = 1,
|
|
Title = "Lecture",
|
|
StartsAt = DateTime.UtcNow.AddDays(-1),
|
|
EndsAt = DateTime.UtcNow.AddDays(-1).AddHours(2),
|
|
IsOpen = true,
|
|
MaxEnrollments = 30
|
|
});
|
|
db.Reviews.Add(new Review
|
|
{
|
|
Id = 1,
|
|
LectureId = 1,
|
|
UserId = 1,
|
|
Rating = ReviewRating.Like,
|
|
Text = "Useful review",
|
|
LlmStatus = ReviewLlmStatus.Pending
|
|
});
|
|
await db.SaveChangesAsync();
|
|
}
|
|
|
|
private static AppDbContext CreateDbContext()
|
|
{
|
|
var options = new DbContextOptionsBuilder<AppDbContext>()
|
|
.UseInMemoryDatabase($"LlmAnalysisServiceTests_{Guid.NewGuid()}")
|
|
.Options;
|
|
return new AppDbContext(options);
|
|
}
|
|
}
|