How do you use Moq to fake a dependency?
Quick Answer
Create a mock of the interface, configure its behaviour with Setup(...).Returns(...) (or ReturnsAsync), pass mock.Object into the class under test, then optionally Verify(...) that a method was called. Use It.IsAny<T>() / It.Is<T>(predicate) to match arguments.
I make a Mock<IEmailSender>, configure the methods I care about with Setup(x => x.SendAsync(It.IsAny<string>())).ReturnsAsync(true), pass mock.Object into the service I'm testing, run the test, and then either assert on the outcome or call mock.Verify(x => x.SendAsync(...), Times.Once) if the point is that an email got sent. It.IsAny and It.Is with a predicate let me match on the arguments. You can only mock interfaces and virtual members, which is another nudge toward coding against interfaces.
- You can only mock interfaces, abstract members, or virtual members — another reason to program to interfaces.
- Prefer stubbing (
Setup().Returns()) and asserting on the result overVerify()on every interaction. MockBehavior.Strictfails on any unconfigured call — useful to catch unexpected interactions, noisy otherwise.- NSubstitute is a popular alternative with a lighter syntax (
sub.GetById(1).Returns(x)).
var repo = new Mock<IOrderRepository>();
repo.Setup(r => r.GetByIdAsync(5)).ReturnsAsync(new Order { Id = 5, Total = 100 });
var service = new OrderService(repo.Object);
var dto = await service.GetSummaryAsync(5);
Assert.Equal(100, dto.Total);
repo.Verify(r => r.GetByIdAsync(5), Times.Once);