c# - AutoFixture+Moq - 卡住模拟类以防止设置

标签 c# unit-testing moq autofixture

我想了解为什么当我卡住模拟类而不是模拟接口(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/ 如果我尝试使用模拟界面,它会起作用。

[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 是一个具体的(非抽象的)类,AutoFixture.AutoMoq 不会使用 Moq 创建那些类。这是设计的,因为 AutoFixture 内核已经处理了“普通”类的创建。

You can change this behaviour如果你愿意的话。不过,我通常会考虑必须这样做是一种设计味道。不过,在这种情况下很难判断,因为您已经很好地将问题减少到最小程度。但是,问题在于,如此处所示,MyService 不会增加任何值。我确定这不是您的真实代码的样子,但由于我无法猜测您的真实代码的样子,所以我无法判断是否可以进行更好的设计。

关于c# - AutoFixture+Moq - 卡住模拟类以防止设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42606650/

相关文章:

c# - 单元测试自定义 View 引擎

java - 如何比较 JUnit 测试用例中的文件?

c# - 基于对同一模拟对象的早期 void 方法调用定义模拟响应

c# - 如何强制最小起订量调用构造函数?

c# - 405 方法不允许 Web API 2

c# - 这是实现 ITaggable 功能的合适方法吗?

c# - 全局钩子(Hook) mousedown 和 keypress 事件未触发

c# - Task.Factory.FromAsync 和 BeginX/EndX 之间的区别?

python - Django 测试 : Using a login decorator for test cases

c# - 使用最小起订量模拟具有约束的通用方法