How to mock dependencies to unit test behavior without real implementations.
dotnet add HandsOn.Tests package Moq
# NUnit already present if you used 'dotnet new nunit'
// Domain model
public class Doctor
{
public int DoctorId { get; set; }
public string Name { get; set; } = string.Empty;
}
// Dependency to mock
public interface IDoctorRepository
{
Doctor? GetById(int id);
void Add(Doctor doctor);
}
// SUT (System Under Test)
public class DoctorService
{
private readonly IDoctorRepository _repo;
public DoctorService(IDoctorRepository repo) => _repo = repo;
public Doctor Register(string name)
{
var doc = new Doctor { Name = name };
_repo.Add(doc);
return doc;
}
public string Describe(int id)
{
var d = _repo.GetById(id);
return d == null ? "Not found" : $"#{d.DoctorId} {d.Name}";
}
}
// Tests (NUnit + Moq)
using Moq;
using NUnit.Framework;
[TestFixture]
public class DoctorServiceTests
{
[Test]
public void Register_AddsDoctor_AndReturnsIt()
{
// Arrange
var mockRepo = new Mock();
var service = new DoctorService(mockRepo.Object);
// Act
var result = service.Register("Dr. Ada");
// Assert
mockRepo.Verify(r => r.Add(It.Is(d => d.Name == "Dr. Ada")), Times.Once);
Assert.That(result.Name, Is.EqualTo("Dr. Ada"));
}
[Test]
public void Describe_ReturnsFormatted_WhenDoctorExists()
{
// Arrange
var mockRepo = new Mock();
mockRepo.Setup(r => r.GetById(5)).Returns(new Doctor { DoctorId = 5, Name = "Dr. Bob" });
var service = new DoctorService(mockRepo.Object);
// Act
var text = service.Describe(5);
// Assert
Assert.That(text, Is.EqualTo("#5 Dr. Bob"));
}
[Test]
public void Describe_ReturnsNotFound_WhenMissing()
{
var mockRepo = new Mock();
mockRepo.Setup(r => r.GetById(It.IsAny())).Returns((Doctor?)null);
var service = new DoctorService(mockRepo.Object);
var text = service.Describe(99);
Assert.That(text, Is.EqualTo("Not found"));
}
}
Common Moq patterns: Setup to define behavior, Verify to assert calls, It.Is/It.IsAny for argument matching, and Times for call count.
var mock = new Moq.Mock();
mock.Setup(r => r.GetById(-1)).Throws(new ArgumentException("Invalid id"));
// Async example
public interface IAsyncDoctorRepository { Task GetAsync(int id); }
var m2 = new Moq.Mock();
m2.Setup(r => r.GetAsync(1)).ReturnsAsync(new Doctor { DoctorId = 1, Name = "Async Doc" });