| name | xunit |
| description | Writes and manages xUnit tests with FluentAssertions and Moq for BotMind mod testing.
Use when: writing unit tests, creating test fixtures, mocking EFT/Unity dependencies, or validating bot behavior logic.
|
| allowed-tools | Read, Edit, Write, Glob, Grep, Bash |
xUnit Skill
Unit testing for BotMind uses xUnit 2.9.x with FluentAssertions for readable assertions and Moq for mocking EFT game classes that can't be instantiated directly. Tests live in src/tests/ and follow the MethodName_Scenario_ExpectedResult naming convention.
Quick Start
Basic Test Structure
using FluentAssertions;
using Moq;
using Xunit;
namespace Blackhorse311.BotMind.Tests;
public class LootFinderTests
{
[Fact]
public void FindLootableTargets_NoTargetsInRange_ReturnsEmptyList()
{
var finder = new LootFinder(searchRadius: 50f);
var targets = finder.FindLootableTargets(Vector3.zero);
targets.Should().BeEmpty();
}
}
Mocking EFT Classes
[Fact]
public void IsActive_BotInCombat_ReturnsFalse()
{
var mockBotOwner = new Mock<BotOwner>();
mockBotOwner.Setup(b => b.Memory.IsUnderFire).Returns(true);
var layer = new LootingLayer(mockBotOwner.Object);
layer.IsActive().Should().BeFalse();
}
Key Concepts
| Concept | Usage | Example |
|---|
[Fact] | Single test case | [Fact] public void Method_Does_Thing() |
[Theory] | Parameterized tests | [Theory] [InlineData(1)] [InlineData(2)] |
Should() | FluentAssertions entry | result.Should().Be(expected) |
Mock<T> | Create mock object | new Mock<BotOwner>() |
Setup() | Define mock behavior | .Setup(x => x.Prop).Returns(val) |
Common Patterns
Testing State Machines
When: Testing logic classes with multiple states (LootCorpseLogic, HealPatientLogic)
[Fact]
public void Update_ReachesTarget_TransitionsToLootingState()
{
var logic = CreateLootCorpseLogic(distanceToTarget: 1.0f);
logic.Update(new ActionData());
logic.CurrentState.Should().Be(ELootState.Looting);
}
Testing Configuration Bounds
When: Validating BepInEx config constraints
[Theory]
[InlineData(5, 10)]
[InlineData(250, 200)]
[InlineData(50, 50)]
public void SearchRadius_ClampsToValidRange(float input, float expected)
{
var config = new BotMindConfig { SearchRadius = input };
config.SearchRadius.Should().Be(expected);
}
Running Tests
dotnet test src/tests/Blackhorse311.BotMind.Tests.csproj
dotnet test --logger "console;verbosity=detailed"
dotnet test --filter "FullyQualifiedName~LootFinderTests"
dotnet test --collect:"XPlat Code Coverage"
See Also
- patterns - Test patterns and FluentAssertions usage
- workflows - TDD workflows and CI integration
Related Skills
- See the csharp skill for language patterns used in tests
- See the dotnet skill for build and project configuration