AutoFixture+Moq - 冻结模拟 class 防止设置
AutoFixture+Moq - Freezing a mocked class prevent from setup
我想了解为什么当我冻结模拟的 class 而不是模拟的接口时我的测试失败
[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/ 如果我尝试使用模拟界面,它会起作用。
[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/ 如果我使用 'inject' 而不是冻结,它会起作用:
[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;
}
}
我的自动修复版本:3.6.5.0
MyWebRequest
是具体的(非抽象的)class,而 AutoFixture.AutoMoq 不会使用 [=17= 创建那些]起订量。这是 设计,因为 AutoFixture 内核已经处理 'normal' classes.[=13= 的创建]
You can change this behaviour 如果你愿意的话。不过,我通常会考虑必须这样做是一种设计味道。不过,在这种情况下很难判断,因为您已经很好地将问题减少到最小程度。但是,问题在于,如此处所示,MyService
不会增加任何值。我确定这不是您的真实代码的样子,但由于我无法猜测您的真实代码的样子,所以我无法判断是否可以进行更好的设计。
我想了解为什么当我冻结模拟的 class 而不是模拟的接口时我的测试失败
[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/ 如果我尝试使用模拟界面,它会起作用。
[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/ 如果我使用 'inject' 而不是冻结,它会起作用:
[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;
}
}
我的自动修复版本:3.6.5.0
MyWebRequest
是具体的(非抽象的)class,而 AutoFixture.AutoMoq 不会使用 [=17= 创建那些]起订量。这是 设计,因为 AutoFixture 内核已经处理 'normal' classes.[=13= 的创建]
You can change this behaviour 如果你愿意的话。不过,我通常会考虑必须这样做是一种设计味道。不过,在这种情况下很难判断,因为您已经很好地将问题减少到最小程度。但是,问题在于,如此处所示,MyService
不会增加任何值。我确定这不是您的真实代码的样子,但由于我无法猜测您的真实代码的样子,所以我无法判断是否可以进行更好的设计。