I'd like to understand why my test fails when I'm freezing a mocked class instead of an mocked interface
[Fact]
public void MethodeName()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var webRequestMock = fixture.Freeze<Mock<MyWebRequest>>(); // freezing a class + setuping a return value
webRequestMock.Setup(a => a.GetData())
.Returns("Foo");
var myService = fixture.Create<MyService>();
var actual = myService.GetData();
webRequestMock.Verify(a => a.GetData(), Times.Once()); // Failed it's never called once
Assert.Equal("Foo", actual); // Failed, if we comment previous line, 'actual' value is always empty
}
public class MyService
{
private readonly MyWebRequest _request;
public MyService(MyWebRequest request)
{
_request = request;
}
public string GetData()
{
var data = _request.GetData();
return data;
}
}
public class MyWebRequest
{
public virtual string GetData() // you can see here, the method is well virtual, and should be overridable by moq.
{
return string.Empty;
}
}
1/ If I try with a mocked interface, it works.
[Fact]
public void MethodeName()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
const string expected = "Foo";
var webRequestMock = fixture.Freeze<Mock<IMyWebRequest>>();
webRequestMock.Setup(a => a.GetData())
.Returns("Foo");
var myService = fixture.Create<MyService>();
var actual = myService.GetData();
webRequestMock.Verify(a => a.GetData(), Times.Once()); // Success
Assert.Equal(expected, actual); // Success
}
public class MyService
{
private readonly IMyWebRequest _request;
public MyService(IMyWebRequest request)
{
_request = request;
}
public string GetData()
{
var data = _request.GetData();
return data;
}
}
public interface IMyWebRequest
{
string GetData();
}
public class MyWebRequest : IMyWebRequest
{
public virtual string GetData()
{
return string.Empty;
}
}
2/ If I use 'inject' instead of freeze, it works:
[Fact]
public void MethodeName()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
const string expected = "Foo";
var webRequestMock = new Mock<MyWebRequest>();
webRequestMock.Setup(a => a.GetData()).Returns("Foo");
fixture.Inject(webRequestMock.Object);
var myService = fixture.Create<MyService>();
var actual = myService.GetData();
webRequestMock.Verify(a => a.GetData(), Times.Once()); // Success
Assert.Equal(expected, actual); // Success
}
public class MyService
{
private readonly MyWebRequest _request;
public MyService(MyWebRequest request)
{
_request = request;
}
public string GetData()
{
var data = _request.GetData();
return data;
}
}
public class MyWebRequest
{
public virtual string GetData()
{
// make WebRequest
return string.Empty;
}
}
My autofixture version: 3.6.5.0
MyWebRequest
is a concrete (non-abstract) class, and AutoFixture.AutoMoq doesn't create those using Moq. This is by design, since the AutoFixture kernel already deals with creation of 'normal' classes.
You can change this behaviour if you'd like. Often, though, I'd consider having to do this a design smell. It's difficult to tell in this case, though, because you've done a good job of reducing the problem to a minimal repro. The problem with this, though, is that as presented here, MyService
doesn't add any value. I'm sure that's not what your real code looks like, but since I can't guess what your real code looks like, I can't tell if a better design would be possible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With