簡體   English   中英

AutoFixture + Moq - 凍結模擬類可防止設置

[英]AutoFixture+Moq - Freezing a mocked class prevent from setup

我想理解為什么當我凍結一個模擬類而不是模擬接口時我的測試失敗了

[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 /如果我使用'注入'而不是凍結,它可以工作:

[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內核已經處理了“普通”類的創建。

如果您願意, 可以更改此行為 但是,我經常認為必須這樣做一個設計氣味。 但是,在這種情況下很難說,因為你已經很好地將問題減少到最小的重復。 但問題是,如此處所示, MyService不會添加任何值。 我確定這不是你的真實代碼的樣子,但由於我無法猜出你的真實代碼是什么樣的,我無法分辨出更好的設計是否可行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM