簡體   English   中英

Moq SetupSequence不起作用

[英]Moq SetupSequence doesn't work

我嘗試使用Moq 4.5框架的SetupSequence方法。

應該嘲笑的類:

public class OutputManager {
    public virtual string WriteMessage(string message) {
    // write a message
    }
}

嘲笑:

var outputManagerMock = new Mock<OutputManager>();
var writeMessageCalls = 0;
var currentMessage = String.Empty;

outputManagerMock.Setup(o => o.WriteMessage(It.IsAny<string>())).Callback((string m) => {
    writeMessageCalls++;
    message = m;
});

此代碼可以正常工作。 但我想為WriteMessage方法的每個調用設置不同的設置。 好吧,我使用SetupSequence而不是Setup

var outputManagerMock = new Mock<OutputManager>();
var writeMessageCalls = 0;
var firstMessage = String.Empty;
var secondMessage = String.Empty;

outputManagerMock.SetupSequence(o => o.WriteMessage(It.IsAny<string>()))
.Callback((string m) => {
    writeMessageCalls++;
    firstMessage = m;
}).Callback((string m) => {
    writeMessageCalls++;
    secondMessage = m;
});

然后我得到了錯誤:

錯誤CS0411方法的類型參數
無法從用法中推斷出'SequenceExtensions.SetupSequence<TMock, TResult>(Mock<TMock>, Expression<Func<TMock, TResult>>)'
嘗試顯式指定類型參數。

我在這里找到了可能的解決方案-Moq中的SetupSequence 但這似乎是一種解決方法。

SetupSequence用於根據嘗試使用正在建立的方法的次數來設置返回序列。 一個基於您的代碼的示例,該示例演示了我在說什么:

outputManagerMock.SetupSequence(o => o.WriteMessage(It.IsAny<string>()))
.Returns("Hello for the first attempt!")
.Returns("This is the second attempt to access me!")
.Throws(new Exception());

如果OutputManager是其他類的依賴項,則應考慮抽象該類,以使其更易於模擬測試。

public interface IOutputManager {
    string WriteMessage(string message);
}

這將意味着該接口的實現與添加接口后的外觀類似。

public class OutputManager : IOutputManager {
    public string WriteMessage(string message) {
        // write a message
    }
}

假設您最初嘗試模擬OutputManager則這里的假設是它不是受測系統,因為您通常不模擬測試目標,而是模擬其依賴項。

因此,假設一個依賴類看起來像這樣。

public class DependentOnIOutputManager {
    private IOutputManager outputManager;

    public DependentOnIOutputManager(IOutputManager outputManager) {
        this.outputManager = outputManager;
    }

    public string SomeMethod(string message) {        
        // write a message
        var output = outputManager.WriteMessage(message);
        //...other code
        return output;
    }
}

然后,示例測試可能如下所示。

[TestMethod]
public void Moq_SetupSequence_Example() {
    //Arrange
    var mock = new Mock<IOutputManager>();

    mock.SetupSequence(x => x.WriteMessage(It.IsAny<string>()))
        .Returns("first")
        .Returns("second")
        .Throws<InvalidOperationException>();

    var outputManager = mock.Object;

    var sut = new DependentOnIOutputManager(outputManager);

    //Act
    var first = sut.SomeMethod("1st");

    var second = sut.SomeMethod("2nd");

    Exception e = null;
    try {
        sut.SomeMethod("3rd");
    } catch (InvalidOperationException ex) {
        e = ex;
    }

    //Assert
    Assert.IsNotNull(first);
    Assert.IsNotNull(second);
    Assert.IsNotNull(e);
}

暫無
暫無

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

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