Moq установки перекрываются. Что будет, если настроить какой-либо случай и конкретный после него? - PullRequest
1 голос
/ 21 февраля 2020

Я хочу установить возвращаемое значение для вызова с любыми аргументами, кроме одного указанного случая, и другого возвращаемого значения для этого одного случая. Предоставляет ли следующий код ожидаемое поведение? Пройдет ли тест? И гарантируется ли это для другой возможной ситуации, которая следует за описанной структурой?

interface ISomeInterface
{
    int SomeMethod(string param);
}

[TestMethod]
public void SomeClass_ShouldBehaveProperly_GivenSomeScenario()
{
    var mock = new Mock<ISomeInterface>(MockBehavior.Strict);
    mock.Setup(m => m.SomeMethod(It.IsAny<string>()))
        .Returns(1);
    mock.Setup(m => m.SomeMethod("aSpecificString"))
        .Returns(100);

    Assert.AreEquel(100, mock.Object.SomeMethod("aSpecificString"));
    Assert.AreEquel(1, mock.Object.SomeMethod("anyString"));
}   

А как насчет смешанных установок, например, когда мы устанавливаем «выдает исключение» для любого аргумента, но «возвращает значение» для некоторых указанных ?

mock.Setup(m => m.SomeMethod(It.IsAny<string>()))
    .Throws<Exception>();
mock.Setup(m => m.SomeMethod("aSpecificString"))
    .Returns(100);

Какое поведение ожидается от настройки, представленной в последнем примере кода?


Из принятого ответа на этот вопрос Я знаю, что

Последний вызов выигрывает и аннулирует предыдущие вызовы

Но, мы имеем такое же поведение, когда установки в обратном порядке?

1 Ответ

1 голос
/ 21 февраля 2020

Но разве у нас такое же поведение, когда настройки в обратном порядке?

Нет (Не в этом случае)

После тестируя его, выясняется, что, когда более конкретные c ожидания выполняются после более слабых совпадений, поведение соответствует ожидаемому

Например,

[TestMethod]
public void SomeClass_ShouldBehaveProperly_GivenSomeScenario() {
    var mock = new Mock<ISomeInterface>(); // Works for Strict or Loose
    mock.Setup(m => m.SomeMethod(It.IsAny<string>()))
        .Throws<InvalidOperationException>();
    mock.Setup(m => m.SomeMethod("aSpecificString"))
        .Returns(100);
    mock.Setup(m => m.SomeMethod("anotherString"))
        .Returns(1);

    Assert.AreEqual(100, mock.Object.SomeMethod("aSpecificString")); //PASS
    Assert.AreEqual(1, mock.Object.SomeMethod("anotherString")); //PASS
    Assert.ThrowsException<InvalidOperationException>(() => 
        mock.Object.SomeMethod("anyString")); //PASS
}

Если, однако, такие же ожидания сделаны несколько раз последний выигрывает

Например

[TestMethod]
public void SomeClass_ShouldBehaveProperly_GivenSomeScenario2() {
    var mock = new Mock<ISomeInterface>();
    mock.Setup(m => m.SomeMethod(It.IsAny<string>()))
       .Throws<InvalidOperationException>();
    mock.Setup(m => m.SomeMethod("aSpecificString"))
        .Returns(100);
    mock.Setup(m => m.SomeMethod("aSpecificString"))
        .Returns(1);

    Assert.ThrowsException<InvalidOperationException>(() => 
        mock.Object.SomeMethod("anyString")); //PASS
    Assert.AreEqual(100, mock.Object.SomeMethod("aSpecificString")); //Fail
}
...