我尝试使用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>>)'不能从用法中推断出来。
  尝试显式指定类型参数。


我在这里找到了可能的解决方案-SetupSequence in Moq。但这似乎是一种解决方法。

最佳答案

如果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);
}

关于c# - Moq SetupSequence不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39719702/

10-09 18:19