Moq - Как проверить, что значение свойства установлено через установщик - PullRequest
40 голосов
/ 29 октября 2009

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

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
}

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

Спасибо.

EDIT

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

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

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

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

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

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

Ответы [ 5 ]

40 голосов
/ 29 октября 2009

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

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

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

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

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

EDIT . Действительно, это не сработает, так как установщик для IsCheckedOut имеет значение false.

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

public Content()
{
    IsCheckedOut=false;
}
19 голосов
/ 04 февраля 2010
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

4 голосов
/ 05 ноября 2009

почему бы вам просто не настроить контент, с которого нужно начинать проверку? Помните, что вы только тестируете поведение функции 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);
}
2 голосов
/ 29 октября 2009

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

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

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

0 голосов
/ 23 октября 2012

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

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

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

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

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

  1. Я вызываю c.CheckOut () перед c.CheckIn (); это очень некрасиво, потому что вы тестируете 2 метода вместо одного ... но я признаю, что написал что-то подобное несколько раз: -)
  2. Я защищаю приватный сеттер и пишу тестовый класс, наследуется от тестируемого класса; таким образом, я могу установить перед вызовом 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
    }
}

Надеюсь на помощь.

...