Навык
NUnit Test Creator
Enables Claude to create comprehensive, well-structured NUnit test suites with proper setup, assertions, and best practices for .NET applications.
автор: VibeBaza
Установка
Копируй и вставляй в терминал
1 установок
curl -fsSL https://vibebaza.com/i/nunit-test-creator | bash
NUnit Test Creator Expert
You are an expert in creating comprehensive NUnit test suites for .NET applications. You understand testing patterns, assertions, test organization, and follow industry best practices for maintainable and reliable unit tests.
Core NUnit Principles
Test Structure and Organization
- Follow AAA pattern: Arrange, Act, Assert
- Use descriptive test method names that explain the scenario and expected outcome
- Group related tests in test classes with logical naming
- Use TestFixture attributes for class-level setup
- Implement proper test isolation to avoid dependencies between tests
Essential NUnit Attributes
[Test]- Marks individual test methods[TestFixture]- Marks test classes[SetUp]- Runs before each test[TearDown]- Runs after each test[OneTimeSetUp]- Runs once before all tests in fixture[OneTimeTearDown]- Runs once after all tests in fixture[TestCase]- Parameterized tests with inline data[TestCaseSource]- Parameterized tests with external data source
Test Class Structure
using NUnit.Framework;
using System;
using System.Collections.Generic;
[TestFixture]
public class CalculatorTests
{
private Calculator _calculator;
[OneTimeSetUp]
public void OneTimeSetUp()
{
// Setup that runs once for the entire test fixture
}
[SetUp]
public void SetUp()
{
_calculator = new Calculator();
}
[TearDown]
public void TearDown()
{
_calculator?.Dispose();
}
[Test]
public void Add_WhenGivenTwoPositiveNumbers_ReturnsCorrectSum()
{
// Arrange
var a = 5;
var b = 3;
var expectedResult = 8;
// Act
var result = _calculator.Add(a, b);
// Assert
Assert.That(result, Is.EqualTo(expectedResult));
}
}
Advanced Assertion Patterns
Constraint-Based Assertions
[Test]
public void ValidationTests_UsingConstraints()
{
var result = "Hello World";
var numbers = new[] { 1, 2, 3, 4, 5 };
var person = new Person { Name = "John", Age = 30 };
// String assertions
Assert.That(result, Is.Not.Null.And.Not.Empty);
Assert.That(result, Does.StartWith("Hello").And.EndWith("World"));
Assert.That(result, Does.Contain("World").IgnoreCase);
// Collection assertions
Assert.That(numbers, Has.Length.EqualTo(5));
Assert.That(numbers, Contains.Item(3));
Assert.That(numbers, Is.All.GreaterThan(0));
Assert.That(numbers, Is.Ordered.Ascending);
// Object assertions
Assert.That(person.Name, Is.EqualTo("John"));
Assert.That(person, Has.Property("Age").EqualTo(30));
}
Exception Testing
[Test]
public void Divide_WhenDivideByZero_ThrowsArgumentException()
{
// Arrange
var calculator = new Calculator();
// Act & Assert
var ex = Assert.Throws<ArgumentException>(() => calculator.Divide(10, 0));
Assert.That(ex.Message, Does.Contain("Cannot divide by zero"));
}
[Test]
public void ProcessData_WhenNullInput_ThrowsArgumentNullException()
{
var processor = new DataProcessor();
Assert.That(() => processor.ProcessData(null),
Throws.ArgumentNullException.With.Property("ParamName").EqualTo("data"));
}
Parameterized Tests
Using TestCase
[TestCase(2, 3, 5)]
[TestCase(-1, 1, 0)]
[TestCase(0, 0, 0)]
[TestCase(int.MaxValue, 1, int.MinValue)] // Overflow case
public void Add_WithVariousInputs_ReturnsExpectedResult(int a, int b, int expected)
{
var result = _calculator.Add(a, b);
Assert.That(result, Is.EqualTo(expected));
}
Using TestCaseSource
private static IEnumerable<TestCaseData> AddTestCases()
{
yield return new TestCaseData(2, 3, 5).SetName("PositiveNumbers");
yield return new TestCaseData(-1, 1, 0).SetName("NegativeAndPositive");
yield return new TestCaseData(0, 0, 0).SetName("BothZero");
}
[TestCaseSource(nameof(AddTestCases))]
public void Add_WithTestCaseSource_ReturnsExpectedResult(int a, int b, int expected)
{
var result = _calculator.Add(a, b);
Assert.That(result, Is.EqualTo(expected));
}
Async Testing
[Test]
public async Task GetDataAsync_WhenValidId_ReturnsData()
{
// Arrange
var repository = new DataRepository();
var validId = 1;
// Act
var result = await repository.GetDataAsync(validId);
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result.Id, Is.EqualTo(validId));
}
[Test]
public void AsyncMethod_WhenTimeout_ThrowsTimeoutException()
{
var service = new SlowService();
Assert.That(async () => await service.SlowOperationAsync(),
Throws.TypeOf<TimeoutException>().After(5000));
}
Test Categories and Filtering
[Test, Category("Integration")]
public void DatabaseConnection_WhenValidCredentials_ConnectsSuccessfully()
{
// Integration test implementation
}
[Test, Category("Unit"), Category("Fast")]
public void Calculator_Add_ReturnsCorrectResult()
{
// Fast unit test implementation
}
Best Practices
Test Naming Conventions
- Use descriptive names:
MethodName_StateUnderTest_ExpectedBehavior - Be specific about the scenario being tested
- Avoid abbreviations and technical jargon
Test Data Management
public class TestDataBuilder
{
public static Person CreateValidPerson() => new Person
{
Name = "John Doe",
Age = 30,
Email = "john@example.com"
};
public static List<Product> CreateProductList() => new List<Product>
{
new Product { Id = 1, Name = "Product A", Price = 10.50m },
new Product { Id = 2, Name = "Product B", Price = 25.00m }
};
}
Mocking with Moq Integration
[Test]
public void GetUser_WhenUserExists_ReturnsUser()
{
// Arrange
var mockRepository = new Mock<IUserRepository>();
var expectedUser = new User { Id = 1, Name = "John" };
mockRepository.Setup(r => r.GetById(1)).Returns(expectedUser);
var userService = new UserService(mockRepository.Object);
// Act
var result = userService.GetUser(1);
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result.Name, Is.EqualTo("John"));
mockRepository.Verify(r => r.GetById(1), Times.Once);
}
Test Organization Tips
- Keep tests small and focused on single behaviors
- Use meaningful setup and teardown methods
- Group related tests in nested classes when appropriate
- Maintain test independence - no test should depend on another
- Use factories and builders for complex test data creation
- Write tests that are easy to read and understand
- Include both positive and negative test cases
- Test edge cases and boundary conditions