首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AutoFixture AutoMoq没有为某些属性创建模拟

AutoFixture AutoMoq没有为某些属性创建模拟
EN

Stack Overflow用户
提问于 2015-10-15 16:36:16
回答 1查看 3.1K关注 0票数 5

我将AutoFixture与AutoMoqCustomization一起使用,并试图创建一个包含只读属性的类实例,如下所示:

代码语言:javascript
复制
public override ILog Logger { get; } = LogManager.GetLogger(typeof(MyService));

我的想法是,我应该能够冻结我的测试ILog测试双倍使用:

代码语言:javascript
复制
var log = fixture.Freeze<Mock<ILog>>;

并在主方法调用之后,通过以下方法验证它的调用:

代码语言:javascript
复制
log.Verify(l => l.Warn, Times.Once);

但是,当我调用fixture.Create<MyService>时,AutoFixture并不用模拟ILog替换Logger属性。我还尝试删除默认值LogManager.GetLogger<etc>,在这种情况下,ILog的值是null

其他属性是正确填充的测试双,但不是这个。

作为参考,ILog接口来自ServiceStack的日志框架,如下所示:

代码语言:javascript
复制
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属性:

代码语言:javascript
复制
myServiceMock.Setup(s => s.Logger).Returns(myLoggerMock)

有人能解释一下这件事吗?

复制的步骤

测试

代码语言:javascript
复制
    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))为后缀,但为了查看问题,我在这里省略了它。

代码语言:javascript
复制
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属性仍然是空的,但是其他属性有模拟。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-10-16 08:49:12

AutoMoqCustomization所做的就是将AutoFixture配置为将接口或抽象类型的所有请求委托给Moq。它不会自动为所创建的Test的属性和方法设置任何存根。

然而,就AutoFixture 3.20.0而言,一种新的自动模拟定制正是这样做的-- AutoConfiguredMoqCustomization

代码语言:javascript
复制
var fixture = new Fixture().Customize(new AutoConfiguredMoqCustomization());

启用该自定义,可以确保Moq中的测试加倍配置为从其所有公共属性返回由AutoFixture创建的对象。

但有个问题。作为@dcastro报道,一个bug是在Moq 4.2.1502.911中介绍,它导致只读属性(就像在您的情况下的MyService.Logger属性)在AutoFixture配置之后被AutoFixture覆盖。

因此,即使切换到AutoConfiguredMoqCustomizationLogger属性仍然是空的,因为它是只读的。另一方面,具有返回值的其他属性和方法将被配置为返回由AutoFixture创建的对象。

您现在的最佳选择是开始使用AutoConfiguredMoqCustomization,并将其降级为仍在正确配置只读属性的Moq的早期版本

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33153930

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档