我将AutoFixture与AutoMoqCustomization一起使用,并试图创建一个包含只读属性的类实例,如下所示:
public override ILog Logger { get; } = LogManager.GetLogger(typeof(MyService));我的想法是,我应该能够冻结我的测试ILog测试双倍使用:
var log = fixture.Freeze<Mock<ILog>>;并在主方法调用之后,通过以下方法验证它的调用:
log.Verify(l => l.Warn, Times.Once);但是,当我调用fixture.Create<MyService>时,AutoFixture并不用模拟ILog替换Logger属性。我还尝试删除默认值LogManager.GetLogger<etc>,在这种情况下,ILog的值是null。
其他属性是正确填充的测试双,但不是这个。
作为参考,ILog接口来自ServiceStack的日志框架,如下所示:
public interface ILog
{
bool IsDebugEnabled { get; }
void Debug(object message);
void Debug(object message, Exception exception);
void DebugFormat(string format, params object[] args);
void Error(object message);
void Error(object message, Exception exception);
void ErrorFormat(string format, params object[] args);
void Fatal(object message);
void Fatal(object message, Exception exception);
void FatalFormat(string format, params object[] args);
void Info(object message);
void Info(object message, Exception exception);
void InfoFormat(string format, params object[] args);
void Warn(object message);
void Warn(object message, Exception exception);
void WarnFormat(string format, params object[] args);
}我还验证了手动创建Mock并使用Moq设置它们是否有效--使用以下方法正确地用Mock替换了ILog属性:
myServiceMock.Setup(s => s.Logger).Returns(myLoggerMock)有人能解释一下这件事吗?
复制的步骤
测试
using ServiceStack;
using ServiceStack.Logging;
using ServiceStack.Web;
using MyApp;
[Test]
public void LogTest()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var log = fixture.Freeze<Mock<ILog>>();
var request = fixture.Freeze<Mock<IRequest>>();
var response = new Mock<IResponse>();
var service = fixture.Create<MyService>();
request.Setup(r => r.Response).Returns(response.Object);
service.Post(null);
log.Verify(l => l.Warn(It.IsAny<string>()), Times.Once());
}服务类- NB:通常情况下,Logger属性将以= LogManager.GetLogger(typeof(MyService))为后缀,但为了查看问题,我在这里省略了它。
using ServiceStack;
using ServiceStack.Logging;
namespace MyApp
{
public class MyService : BaseService
{
public override ILog Logger { get; }
public MyResponse Post(MyRequest request)
{
if (request != null) return new MyResponse() {Message = request.Message};
Logger.Warn("Null request object");
return null;
}
}
public abstract class BaseService : Service
{
public abstract ILog Logger { get; }
}
public class MyRequest
{
public string Message { get; set; }
}
public class MyResponse
{
public string Message { get; set; }
}
}如果您在service.Post(null)行上的断点,您将看到ILog属性仍然是空的,但是其他属性有模拟。
发布于 2015-10-16 08:49:12
AutoMoqCustomization所做的就是将AutoFixture配置为将接口或抽象类型的所有请求委托给Moq。它不会自动为所创建的Test的属性和方法设置任何存根。
然而,就AutoFixture 3.20.0而言,一种新的自动模拟定制正是这样做的-- AutoConfiguredMoqCustomization
var fixture = new Fixture().Customize(new AutoConfiguredMoqCustomization());启用该自定义,可以确保Moq中的测试加倍配置为从其所有公共属性返回由AutoFixture创建的对象。
但有个问题。作为@dcastro报道,一个bug是在Moq 4.2.1502.911中介绍,它导致只读属性(就像在您的情况下的MyService.Logger属性)在AutoFixture配置之后被AutoFixture覆盖。
因此,即使切换到AutoConfiguredMoqCustomization,Logger属性仍然是空的,因为它是只读的。另一方面,具有返回值的其他属性和方法将被配置为返回由AutoFixture创建的对象。
您现在的最佳选择是开始使用AutoConfiguredMoqCustomization,并将其降级为仍在正确配置只读属性的Moq的早期版本。
https://stackoverflow.com/questions/33153930
复制相似问题