I am trying to test a service that makes use of provider that gets some value from a database and uses it inside the service before returning some value. When debugging the test, the mocked provider works fine. But when running the test in its entirety then the provider always returns null.
[Theory]
[AutoStackoverFlowData]
public async Task TestingService(Service sut, [Frozen] Mock<IProvider> providerMock)
{
providerMock.Setup(x => x.GetGreeting(It.IsAny<int>())).ReturnsAsync("Hello Developer");
var s = providerMock.Object.GetGreeting(123); //works returns "Hello Developer"
var greeting = sut.SayHello();
Assert.Equal(greeting, "Hello Developer");
}
public class AutoStackoverFlowData : AutoDataAttribute
{
public AutoStackoverFlowData() : this(new AutoMoqCustomization()) { }
public AutoStackoverFlowData(params ICustomization[] customization)
: base(() => new Fixture().Customize(new AutoMoqCustomization())) { }
}
public class Service
{
private readonly IProvider provider
public Service(IProvider provider)
{
this.provider= provider;
}
public async Task<string> SayHello()
{
int someNum= 123;
var temp = await subProvider.GetGreeting(someNum);
return temp;
}
}
public interface IProvider
{
Task<string> GetGreeting(int id);
}
Order is important when using [Frozen]. Always have your [Frozen] variables as the first parameters in your test cases. It's a simple fix:
[Theory]
[AutoStackoverFlowData]
public async Task TestingService([Frozen] Mock<IProvider> providerMock, Service sut)
{
providerMock.Setup(x => x.GetGreeting(It.IsAny<int>())).ReturnsAsync("Hello Developer");
var s = providerMock.Object.GetGreeting(123);
var greeting = await sut.SayHello();
Assert.Equal("Hello Developer", greeting);
}
The reason why the order of parameters matter at all is because this enables you to generate one or more values of a datatype BEFORE you freeze it.