xunit

xUnit.net - Quick Reference

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "xunit" with this command: npx skills add claude-dev-suite/claude-dev-suite/claude-dev-suite-claude-dev-suite-xunit

xUnit.net - Quick Reference

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: xunit for comprehensive documentation.

Basic Tests

public class UserServiceTests { [Fact] public async Task GetById_ExistingUser_ReturnsUser() { // Arrange var repository = new Mock<IUserRepository>(); repository.Setup(r => r.GetByIdAsync(1)) .ReturnsAsync(new User { Id = 1, Name = "Alice" });

    var service = new UserService(repository.Object, Mock.Of&#x3C;ILogger&#x3C;UserService>>());

    // Act
    var result = await service.GetByIdAsync(1);

    // Assert
    Assert.NotNull(result);
    Assert.Equal("Alice", result.Name);
}

[Fact]
public async Task GetById_NonExistingUser_ReturnsNull()
{
    var repository = new Mock&#x3C;IUserRepository>();
    repository.Setup(r => r.GetByIdAsync(999)).ReturnsAsync((User?)null);

    var service = new UserService(repository.Object, Mock.Of&#x3C;ILogger&#x3C;UserService>>());

    var result = await service.GetByIdAsync(999);

    Assert.Null(result);
}

}

Theory (Parameterized Tests)

[Theory] [InlineData("", false)] [InlineData("a", false)] [InlineData("ab", true)] [InlineData("valid@email.com", true)] public void Validate_Name_ReturnsExpected(string name, bool expected) { var validator = new UserValidator(); var result = validator.IsValidName(name); Assert.Equal(expected, result); }

[Theory] [MemberData(nameof(GetTestUsers))] public async Task Create_ValidUser_Succeeds(CreateUserRequest request) { // Test with complex objects }

public static IEnumerable<object[]> GetTestUsers() { yield return new object[] { new CreateUserRequest("Alice", "alice@test.com") }; yield return new object[] { new CreateUserRequest("Bob", "bob@test.com") }; }

Mocking with Moq

// Setup var mock = new Mock<IUserRepository>();

// Return value mock.Setup(r => r.GetByIdAsync(It.IsAny<int>())) .ReturnsAsync(new User { Id = 1, Name = "Test" });

// Callback mock.Setup(r => r.AddAsync(It.IsAny<User>())) .Callback<User>(user => user.Id = 42) .Returns(Task.CompletedTask);

// Verify mock.Verify(r => r.AddAsync(It.Is<User>(u => u.Name == "Alice")), Times.Once); mock.Verify(r => r.DeleteAsync(It.IsAny<int>()), Times.Never);

// Sequence mock.SetupSequence(r => r.GetByIdAsync(1)) .ReturnsAsync(new User { Name = "First" }) .ReturnsAsync(new User { Name = "Second" });

Mocking with NSubstitute

var repository = Substitute.For<IUserRepository>();

// Return value repository.GetByIdAsync(1).Returns(new User { Id = 1, Name = "Test" });

// Verify await repository.Received(1).AddAsync(Arg.Is<User>(u => u.Name == "Alice")); await repository.DidNotReceive().DeleteAsync(Arg.Any<int>());

Fixtures (Shared Context)

// Class fixture - shared per test class public class DatabaseFixture : IAsyncLifetime { public AppDbContext Context { get; private set; } = default!;

public async Task InitializeAsync()
{
    var options = new DbContextOptionsBuilder&#x3C;AppDbContext>()
        .UseInMemoryDatabase(Guid.NewGuid().ToString())
        .Options;
    Context = new AppDbContext(options);
    await Context.Database.EnsureCreatedAsync();
}

public async Task DisposeAsync()
{
    await Context.DisposeAsync();
}

}

public class UserRepositoryTests : IClassFixture<DatabaseFixture> { private readonly AppDbContext _context;

public UserRepositoryTests(DatabaseFixture fixture)
{
    _context = fixture.Context;
}

}

// Collection fixture - shared across test classes [CollectionDefinition("Database")] public class DatabaseCollection : ICollectionFixture<DatabaseFixture> { }

[Collection("Database")] public class OrderRepositoryTests { }

FluentAssertions (Optional)

// Install: dotnet add package FluentAssertions result.Should().NotBeNull(); result.Name.Should().Be("Alice"); result.Age.Should().BeGreaterThan(0).And.BeLessThan(150); users.Should().HaveCount(3).And.OnlyContain(u => u.IsActive);

Anti-Patterns

Anti-Pattern Why It's Bad Correct Approach

Testing implementation details Brittle tests Test behavior

Shared mutable state Flaky tests Use fresh fixtures per test

No assertion message Hard to debug Use descriptive assertions

Testing private methods Coupling to internals Test through public API

Quick Troubleshooting

Issue Likely Cause Solution

Test not discovered Missing [Fact] /[Theory]

Add test attribute

Fixture not shared Missing IClassFixture<T>

Implement fixture interface

Mock returns null Missing setup Add .Setup() for the call

Async test deadlock Missing async keyword Use async Task return type

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

cron-scheduling

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

token-optimization

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

webrtc

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

react-19

No summary provided by upstream source.

Repository SourceNeeds Review