mirror of
https://github.com/dotnet/skills.git
synced 2026-09-20 09:49:54 +08:00
948a9a52ef
* Add exp-mock-usage-analysis skill and evaluation New experimental skill that detects unused, redundant, or unnecessary mocks in .NET test suites. Covers Moq, NSubstitute, FakeItEasy, and manual test doubles. - SKILL.md with 6-step workflow: gather code, classify mocks, detect anti-patterns, incorporate runtime data, generate recommendations, report findings - eval.yaml with 10 scenarios: trivial type mocking, unused setups, redundant configs, stable utility mocks, well-placed mocks (no false positives), NSubstitute support, FakeItEasy support, setup sprawl, and 2 non-activation boundary tests - Fixture files for each scenario with production + test code - CODEOWNERS entry for @dotnet/dotnet-testing * Remove no-headroom scenarios, increase NSubstitute timeout Remove 4 scenarios where baseline already scores 5.0/5 (model handles these well without skill guidance): - Detect mocking of DTOs, records, and enums - Recognize well-placed mocks without inventing false positives - Decline when asked about non-mock test anti-patterns - Decline mock framework migration request Increase NSubstitute scenario timeout from 120s to 180s to avoid baseline timeouts impacting scoring. Remaining 6 scenarios all show positive skill impact (3→5, 3→4, etc). * Document areas the model handles well without the skill Add a subsection under 'When Not to Use' listing mock-related tasks where the base model already scores 5.0/5 without skill guidance: - Mocking trivial types (DTOs, records, enums) - Recognizing well-placed mocks (no false positives) * Fix md * Improve
87 lines
2.9 KiB
C#
87 lines
2.9 KiB
C#
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using Moq;
|
|
using UserManagement;
|
|
|
|
namespace UserManagement.Tests;
|
|
|
|
[TestClass]
|
|
public sealed class AuthenticationServiceTests
|
|
{
|
|
private Mock<IUserStore> _mockUserStore = null!;
|
|
private Mock<IPasswordHasher> _mockHasher = null!;
|
|
private Mock<ILogger<AuthenticationService>> _mockLogger = null!;
|
|
private Mock<IOptions<UserManagerOptions>> _mockOptions = null!;
|
|
private AuthenticationService _service = null!;
|
|
|
|
[TestInitialize]
|
|
public void Setup()
|
|
{
|
|
_mockUserStore = new Mock<IUserStore>();
|
|
_mockHasher = new Mock<IPasswordHasher>();
|
|
_mockLogger = new Mock<ILogger<AuthenticationService>>();
|
|
_mockOptions = new Mock<IOptions<UserManagerOptions>>();
|
|
|
|
_mockOptions.Setup(o => o.Value).Returns(new UserManagerOptions
|
|
{
|
|
MaxLoginAttempts = 5,
|
|
LockoutDuration = TimeSpan.FromMinutes(15)
|
|
});
|
|
|
|
_service = new AuthenticationService(
|
|
_mockUserStore.Object,
|
|
_mockHasher.Object,
|
|
_mockLogger.Object,
|
|
_mockOptions.Object);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Login_ValidCredentials_ReturnsTrue()
|
|
{
|
|
var user = new User(1, "alice@example.com", "hashed", 0, null);
|
|
_mockUserStore.Setup(s => s.FindByEmail("alice@example.com")).Returns(user);
|
|
_mockHasher.Setup(h => h.Verify("password123", "hashed")).Returns(true);
|
|
|
|
var result = _service.Login("alice@example.com", "password123");
|
|
|
|
Assert.IsTrue(result);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Login_InvalidPassword_ReturnsFalse()
|
|
{
|
|
var user = new User(1, "alice@example.com", "hashed", 0, null);
|
|
_mockUserStore.Setup(s => s.FindByEmail("alice@example.com")).Returns(user);
|
|
_mockHasher.Setup(h => h.Verify("wrong", "hashed")).Returns(false);
|
|
|
|
var result = _service.Login("alice@example.com", "wrong");
|
|
|
|
Assert.IsFalse(result);
|
|
_mockUserStore.Verify(s => s.Update(It.Is<User>(u => u.FailedAttempts == 1)), Times.Once);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Login_UnknownEmail_ReturnsFalse()
|
|
{
|
|
_mockUserStore.Setup(s => s.FindByEmail("unknown@example.com")).Returns((User?)null);
|
|
|
|
var result = _service.Login("unknown@example.com", "any");
|
|
|
|
Assert.IsFalse(result);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Login_LockedAccount_ReturnsFalse()
|
|
{
|
|
var user = new User(1, "alice@example.com", "hashed", 5, DateTime.UtcNow.AddMinutes(10));
|
|
_mockUserStore.Setup(s => s.FindByEmail("alice@example.com")).Returns(user);
|
|
// These setups are never reached because account is locked
|
|
_mockHasher.Setup(h => h.Verify(It.IsAny<string>(), It.IsAny<string>())).Returns(true);
|
|
|
|
var result = _service.Login("alice@example.com", "password123");
|
|
|
|
Assert.IsFalse(result);
|
|
}
|
|
}
|