DeutschLernen/Tests/Unit/Domain/Entities/UserTests.cs
Lasse Rune Hansen 6bcf592918 feat(backend): complete unit tests for User Authentication feature
- Fix MSTest compatibility with .NET 9.0 by upgrading to MSTest.TestFramework 4.2.3
- Move Tests directory to solution level (Tests/) to prevent test files from being compiled with GermanApp
- Update test project references to point to GermanApp/GermanApp.csproj
- Add InternalsVisibleTo attributes for test assemblies
- Make RefreshToken properties internal for testability
- Fix User.ChangeEmail null handling
- Add 46 comprehensive unit tests for User and RefreshToken domain entities
- All tests passing successfully

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-05 17:07:15 +02:00

428 lines
10 KiB
C#

using System;
using GermanApp.Domain.Entities;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace GermanApp.Tests.Unit.Domain.Entities;
/// <summary>
/// Unit tests for User domain entity.
/// Tests the user factory methods and business logic.
/// </summary>
[TestClass]
public class UserTests
{
#region Factory Method Tests
[TestMethod]
[TestCategory("Factory")]
public void Create_WithValidParameters_ReturnsUser()
{
// Arrange
string username = "testuser";
string email = "test@example.com";
string passwordHash = "hashed-password";
// Act
var user = User.Create(username, email, passwordHash);
// Assert
Assert.IsNotNull(user);
Assert.AreEqual(username, user.Username);
Assert.AreEqual(email, user.Email);
Assert.AreEqual(passwordHash, user.PasswordHash);
Assert.AreEqual("A1", user.CurrentLevel);
Assert.AreEqual(0, user.Streak);
Assert.AreEqual(0, user.TotalPoints);
Assert.IsNotNull(user.CreatedAt);
Assert.IsTrue(user.CreatedAt <= DateTime.UtcNow);
}
[TestMethod]
[TestCategory("Factory")]
public void Create_WithEmptyPasswordHash_ReturnsUser()
{
// Arrange
string username = "testuser";
string email = "test@example.com";
string passwordHash = "";
// Act
var user = User.Create(username, email, passwordHash);
// Assert
Assert.IsNotNull(user);
Assert.AreEqual(passwordHash, user.PasswordHash);
}
[TestMethod]
[TestCategory("Factory")]
public void Create_LowercasesEmail()
{
// Arrange
string username = "testuser";
string email = "TEST@EXAMPLE.COM";
string passwordHash = "hashed-password";
// Act
var user = User.Create(username, email, passwordHash);
// Assert
Assert.AreEqual("test@example.com", user.Email);
}
[TestMethod]
[TestCategory("Factory")]
public void Create_WithMixedCaseUsername_PreservesUsernameCase()
{
// Arrange
string username = "TestUser123";
string email = "test@example.com";
string passwordHash = "hashed-password";
// Act
var user = User.Create(username, email, passwordHash);
// Assert
Assert.AreEqual(username, user.Username);
}
#endregion
#region ChangePassword Method Tests
[TestMethod]
[TestCategory("Behavior")]
public void ChangePassword_WithValidHash_UpdatesPassword()
{
// Arrange
var user = User.Create("testuser", "test@example.com", "initial-hash");
string newHash = "new-hashed-password";
// Act
user.ChangePassword(newHash);
// Assert
Assert.AreEqual(newHash, user.PasswordHash);
}
[TestMethod]
[TestCategory("Behavior")]
public void ChangePassword_WithEmptyHash_UpdatesPassword()
{
// Arrange
var user = User.Create("testuser", "test@example.com", "initial-hash");
// Act
user.ChangePassword("");
// Assert
Assert.AreEqual("", user.PasswordHash);
}
[TestMethod]
[TestCategory("Behavior")]
public void ChangePassword_MultipleTimes_UpdatesCorrectly()
{
// Arrange
var user = User.Create("testuser", "test@example.com", "hash1");
// Act
user.ChangePassword("hash2");
user.ChangePassword("hash3");
// Assert
Assert.AreEqual("hash3", user.PasswordHash);
}
#endregion
#region ChangeEmail Method Tests
[TestMethod]
[TestCategory("Behavior")]
public void ChangeEmail_WithValidEmail_UpdatesEmail()
{
// Arrange
var user = User.Create("testuser", "test@example.com", "hash");
var newEmail = "new@example.com";
// Act
user.ChangeEmail(newEmail);
// Assert
Assert.AreEqual("new@example.com", user.Email);
}
[TestMethod]
[TestCategory("Behavior")]
public void ChangeEmail_LowercasesEmail()
{
// Arrange
var user = User.Create("testuser", "test@example.com", "hash");
// Act
user.ChangeEmail("UPPERCASE@EXAMPLE.COM");
// Assert
Assert.AreEqual("uppercase@example.com", user.Email);
}
[TestMethod]
[TestCategory("Behavior")]
public void ChangeEmail_WithMixedCase_Values()
{
// Arrange
var user = User.Create("testuser", "test@example.com", "hash");
// Act
user.ChangeEmail("TeSt@ExAmPlE.cOm");
// Assert
Assert.AreEqual("test@example.com", user.Email);
}
[TestMethod]
[TestCategory("Behavior")]
public void ChangeEmail_WithNullEmail_UpdatesEmailToEmpty()
{
// Arrange
var user = User.Create("testuser", "test@example.com", "hash");
// Act - Note: This won't throw, it will just set to empty string
user.ChangeEmail(null!);
// Assert
Assert.AreEqual("", user.Email);
}
[TestMethod]
[TestCategory("Behavior")]
public void ChangeEmail_WithEmptyString_SetsEmptyEmail()
{
// Arrange
var user = User.Create("testuser", "test@example.com", "hash");
// Act
user.ChangeEmail("");
// Assert
Assert.AreEqual("", user.Email);
}
#endregion
#region Gamification Methods Tests
[TestMethod]
[TestCategory("Gamification")]
public void AddPoints_IncreasesTotalPoints()
{
// Arrange
var user = User.Create("testuser", "test@example.com", "hash");
int initialPoints = user.TotalPoints;
// Act
user.AddPoints(10);
// Assert
Assert.AreEqual(initialPoints + 10, user.TotalPoints);
}
[TestMethod]
[TestCategory("Gamification")]
public void AddPoints_MultipleTimes_AccumulatesCorrectly()
{
// Arrange
var user = User.Create("testuser", "test@example.com", "hash");
// Act
user.AddPoints(10);
user.AddPoints(20);
user.AddPoints(30);
// Assert
Assert.AreEqual(60, user.TotalPoints);
}
[TestMethod]
[TestCategory("Gamification")]
public void AddPoints_WithNegativePoints_DecreasesTotal()
{
// Arrange
var user = User.Create("testuser", "test@example.com", "hash");
user.AddPoints(100);
// Act
user.AddPoints(-10);
// Assert
Assert.AreEqual(90, user.TotalPoints);
}
[TestMethod]
[TestCategory("Gamification")]
public void UpdateStreak_SetsNewStreak()
{
// Arrange
var user = User.Create("testuser", "test@example.com", "hash");
// Act
user.UpdateStreak(5);
// Assert
Assert.AreEqual(5, user.Streak);
}
[TestMethod]
[TestCategory("Gamification")]
public void UpdateStreak_WithZero_ResetsStreak()
{
// Arrange
var user = User.Create("testuser", "test@example.com", "hash");
user.UpdateStreak(10);
// Act
user.UpdateStreak(0);
// Assert
Assert.AreEqual(0, user.Streak);
}
[TestMethod]
[TestCategory("Gamification")]
public void UpdateLevel_SetsNewLevel()
{
// Arrange
var user = User.Create("testuser", "test@example.com", "hash");
// Act
user.UpdateLevel("B1");
// Assert
Assert.AreEqual("B1", user.CurrentLevel);
}
[TestMethod]
[TestCategory("Gamification")]
public void UpdateLevel_ToHigherLevel_UpdatesCorrectly()
{
// Arrange
var user = User.Create("testuser", "test@example.com", "hash");
// Act
user.UpdateLevel("A2");
user.UpdateLevel("B1");
user.UpdateLevel("C1");
// Assert
Assert.AreEqual("C1", user.CurrentLevel);
}
#endregion
#region Property Tests
[TestMethod]
[TestCategory("Property")]
public void Id_HasDefaultValueOfZero()
{
// Arrange & Act
var user = User.Create("testuser", "test@example.com", "hash");
// Assert
Assert.AreEqual(0, user.Id);
}
[TestMethod]
[TestCategory("Property")]
public void Username_HasPrivateSetter()
{
// Arrange
var username = "testuser";
// Act
var user = User.Create(username, "test@example.com", "hash");
// Assert
Assert.AreEqual(username, user.Username);
}
[TestMethod]
[TestCategory("Property")]
public void Email_HasPrivateSetter()
{
// Arrange
var email = "test@example.com";
// Act
var user = User.Create("testuser", email, "hash");
// Assert
Assert.AreEqual(email, user.Email);
}
[TestMethod]
[TestCategory("Property")]
public void PasswordHash_HasPrivateSetter()
{
// Arrange
var passwordHash = "hashed-password-123";
// Act
var user = User.Create("testuser", "test@example.com", passwordHash);
// Assert
Assert.AreEqual(passwordHash, user.PasswordHash);
}
[TestMethod]
[TestCategory("Property")]
public void CurrentLevel_HasDefaultValueOf_A1()
{
// Arrange & Act
var user = User.Create("testuser", "test@example.com", "hash");
// Assert
Assert.AreEqual("A1", user.CurrentLevel);
}
[TestMethod]
[TestCategory("Property")]
public void Streak_HasDefaultValueOfZero()
{
// Arrange & Act
var user = User.Create("testuser", "test@example.com", "hash");
// Assert
Assert.AreEqual(0, user.Streak);
}
[TestMethod]
[TestCategory("Property")]
public void TotalPoints_HasDefaultValueOfZero()
{
// Arrange & Act
var user = User.Create("testuser", "test@example.com", "hash");
// Assert
Assert.AreEqual(0, user.TotalPoints);
}
[TestMethod]
[TestCategory("Property")]
public void CreatedAt_IsSetToCurrentTime()
{
// Arrange
var beforeCreation = DateTime.UtcNow;
// Act
var user = User.Create("testuser", "test@example.com", "hash");
var afterCreation = DateTime.UtcNow;
// Assert
Assert.IsTrue(user.CreatedAt >= beforeCreation);
Assert.IsTrue(user.CreatedAt <= afterCreation);
}
#endregion
}