Подтвердить что ты не робот

Moq - Как проверить, что значение свойства задано с помощью установщика

Рассмотрим этот класс:

public class Content
{      
   public virtual bool IsCheckedOut {get; private set;}
   public virtual void CheckOut()
   {
      IsCheckedOut = true;
   }

   public virtual void CheckIn()
   {
      //Do Nothing for now as demonstrating false positive test.
   }
}

Метод Checkin намеренно пуст. Теперь у меня есть несколько методов тестирования, чтобы проверить статус вызова каждого метода.

[TestMethod]
public void CheckOutSetsCheckedOutStatusToTrue()
{
    Content c = new Content();    
    c.CheckOut();
    Assert.AreEqual(true, c.IsCheckedOut); //Test works as expected
}

[TestMethod]
public void CheckInSetsCheckedOutStatusToFalse()
{
    Content c = new Content();
    c.CheckIn();
    Assert.AreEqual(false, c.IsCheckedOut); //Test does not work as expected
}

Второй тест проходит по неправильным причинам. Итак, как я могу использовать mocking (moq), чтобы проверить, что CheckIn устанавливает свойство IsCheckedOut?

Спасибо.

ИЗМЕНИТЬ

Чтобы уточнить: у меня есть метод, называемый CheckIn(), задачей которого является установить статус IsCheckedOut на false.

Вы увидите в моем тестовом коде выше, что Test вернет false, даже если я не установил значение свойства false; Ожидается, что здесь ничего плохого.

Я думаю, что мой вопрос конкретно: Как я могу проверить, что метод CheckIn() установил для свойства IsCheckedOut значение false? Это то, что я бы назвал поведенческой проверкой.

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

Content c = new Content();    
c.CheckIn();    
Assert.AreEqual(false, c.IsCheckedOut); //State verification

Конечно, я могу ошибаться, поэтому, пожалуйста, помогите мне прояснить эти понятия:)

4b9b3361

Ответ 1

Следующее должно работать. Настройте свой макет как:

var mock=new Mock<IContent>();
mock.SetupSet(content => content.IsCheckedOut=It.IsAny<bool>()).Verifiable();

И после тестового кода:

mock.VerifySet(content => content.IsCheckedOut=It.IsAny<bool>());

Я все равно не тестировал его, поэтому, пожалуйста, скажите мне, работает ли оно для вас.

ИЗМЕНИТЬ. Действительно, это не сработает, поскольку установщик для IsCheckedOut является ложным.

В любом случае, теперь я вижу, что вы никогда не устанавливаете значение IsCheckedOut во время построения класса. Было бы неплохо добавить следующее к классу Content:

public Content()
{
    IsCheckedOut=false;
}

Ответ 2

Mock mockContect = new Mock<Cotent>(); 
mockContent.VerifySet(x => x.IsCheckedOut, Times.Once());

Будет ли это трюк? Не знаете, как входит частный сеттер, чтобы играть так, как это было проверено. но работает для моего публичного сеттера.

Получите это от: http://www.codethinked.com/post/2009/03/10/Beginning-Mocking-With-Moq-3-Part-2.aspx

Ответ 3

почему бы вам просто не настроить начальный контент? Помните, что вы проверяете поведение функции CheckIn.

[TestMethod]
public void CheckInSetsCheckedOutStatusToFalse()
{
    // arrange - create a checked out item
    Content c = new Content();
    c.CheckOut();

    // act - check it in
    c.CheckIn();

    // assert - IsCheckedOut should be set back to false
    Assert.AreEqual(false, c.IsCheckedOut);
}

Ответ 4

Могу ли я предположить, что вы можете подумать об этом не так - как правило, вы должны что-то настраивать, выполнять действие, а затем проверять поведение (результат). В этом случае действительно имеет значение, что установщик не задал значение false - важно иметь в виду, что он является ложным после того, как был реализован данный сценарий. Если вы проводите тесты изолированно, это может показаться немного странным, но для чего-либо ваши тесты будут существовать в наборах.

Ситуация была бы иной, если бы вы тестировали взаимодействие между двумя классами - тогда было бы хорошо настроить ожидаемое значение для средства настройки свойств, поскольку действие настройки - это взаимодействие, которое вы тестируете.

Я не знаком с Moq, поскольку я использую Rhino.Mocks - но я предполагаю, что будет что-то вроде mock.VerifySet(content = > content.IsCheckedOut = It.IsEqual(true));

Ответ 5

Я согласен с вами: насмешка не имеет значения в этом сценарии, потому что она предназначена для проверки взаимодействия между вашим классом (тестированием) и остальным миром, а не для проверки внутреннего механизма вашего класса.

Я думаю, что этот тест

Content c = new Content();    
c.CheckIn();    
Assert.AreEqual(false, c.IsCheckedOut); //State verification

который вы пишете, имеет смысл и не является ложным положительным! Вы должны убедиться, что состояние было таким образом после CheckIn независимо от того, почему это так; если в будущем вы укажете состояние в конструкторе (или другими способами), этот тест сохранит вас, и вы будете вынуждены внедрить метод CheckIn!

В некоторых случаях, подобных вашему, я хочу установить начальное состояние, чтобы быть уверенным, что я не забываю реализовать метод CheckIn; в этом случае я использую 2 метода (первый очень уродливый):

  • Я вызываю c.CheckOut() до c.CheckIn(); это очень уродливо, потому что вы проверяете 2 метода вместо одного... но я признаю, что я написал нечто похожее несколько раз: -)
  • Я делаю приватный сеттер защищенным, и я пишу тестовый класс, который наследуется от тестируемого класса; таким образом, я могу установить свойство true, чтобы вызвать c.CheckIn(), чтобы убедиться, что метод выполняет свою работу.

Вот код:

    public class Content2
{
    public virtual bool IsCheckedOut { get; protected set; }
    public virtual void CheckOut()
    {
        IsCheckedOut = true;
    }

    public virtual void CheckIn()
    {
        //Do Nothing for now as demonstrating false positive test.
    } 
}

    [TestClass]
public class Content2Test : Content2
{
    [TestMethod]
    public void CheckOutSetsCheckedOutStatusToTrue()
    {
        this.CheckOut();
        Assert.AreEqual(true, this.IsCheckedOut); //Test works as expected
    }

    [TestMethod]
    public void CheckInSetsCheckedOutStatusToFalse()
    {
        this.IsCheckedOut = true;
        this.CheckIn();
        Assert.AreEqual(false, this.IsCheckedOut); //Test does not work as expected
    }
}

Надеюсь помочь.