I have the following scenario and I was wandering what is the proper way to test my services. I have 2 services and 2 repositories.
public class ServiceB : IServiceB
{
public ServiceA(IRepoB)
{
}
public async Task AuditInsert(param, param)
{
IRepoB.Insert(param, param)
}
}
public class ServiceA : IServiceA
{
public ServiceA(IRepoA, IServiceB)
{
}
public async bool DoSomething(param)
{
//logic here
IRepoA.Merge(param)
IServiceB.AuditInsert(param, param)
}
}
////// Testing part
public class ServiceATests
{
private readonly ServiceA _sut;
private readonly Mock<IRepoA> _repoA = new(MockBehavior.Strict)
private readonly Mock<ServiceB> _serviceB = new(MockBehavior.Strict)
_repoA.Setup(x => x.Merge(It.IsAny<ParamEntity>)).Return(Task.TaskCompleted)
_serviceB.Setup(x => x.AuditInsert(It.IsAny<ParamEntity>, It.IsAny<ParamEntity>)).Return(Task.TaskCompleted)
_sut = new ServiceA(_repoA.Object, _serviceB.Object)
}
[Fact]
public async Task TestSomething()
{
//arrange
var testParam = {} // an object
//act
await _sut.DoSomething(testParam)
//assert
_repoA.Verify(x => x.Merge(), Times.Once)
_serviceB.Verify(x => x.AuditInsert(It.IsAny<ParamEntity>, It.IsAny<ParamEntity>), Times.Once)
}
The error I get on the act is "invocation failed with mock behaviour strict, all invocations on the mock must have a coresponding setup".
The code fails in ServiceA on the IServiceB.AuditInsert(param, param) line.
Probably is because when I setup ServiceB, I should somehow pass the mock of RepoB? But I do not know how to do that. Or is better if I remove the _serviceB.Verify part and just create a new class to test only the serviceB?
How should this dependency chain be tackeld on the testing part?
I am using xunit with Mock
I have created a small git repo with a project where the error can be replicated https://github.com/masterxfile/xUnitExample/tree/main/WebApplication1
The provided repro results in the following error:
IAuditService.InsertAudit("test", "Yes") invocation failed with mock behavior Strict. Invocation needs to return a value and therefore must have a corresponding setup that provides it.
Adding .Returns(Task.CompletedTask)
to the corresponding mock fixes the issue:
auditService.Setup(x => x.InsertAudit("test", "Yes"))
.Returns(Task.CompletedTask);