Проверка метода была вызвана

Быстрое решение, если вы хотите отображать сообщение или gif загрузчика до тех пор, пока не отобразится диалоговое окно загрузки, следует поместить сообщение в скрытый контейнер, и когда вы нажимаете кнопку, которая генерирует загружаемый файл, вы делаете контейнер видимый. Затем используйте jquery или javascript, чтобы поймать событие фокуса кнопки, чтобы скрыть контейнер, содержащий сообщение

23
задан abatishchev 12 August 2011 в 06:40
поделиться

3 ответа

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

В вашем примере вы вызываете метод Say (), и он возвращает ожидаемый текст. Ваше ожидание не должно не приводить в исполнение конкретную реализацию Say (), то есть вызывать внутренний метод Hello () для возврата этой строки. Вот почему он не проходит проверку, а также почему возвращается строка "", то есть была вызвана фактическая реализация Hello ().

Делая метод Hello общедоступным, кажется, что это позволило Moq перехватить вызов к нему и использовать вместо этого его реализацию. Таким образом, в этом случае тест, кажется, проходит. Тем не менее, в этом сценарии вы не достигли ничего полезного, потому что ваш тест говорит, что когда вы вызываете Say (), результатом является «Hello World», а на самом деле - «».

Я переписал ваш пример, чтобы показать, как я ожидаю, что Moq будет использоваться (не обязательно окончательно, но, надеюсь, ясно.

public interface IHelloProvider
{
    string Hello();
}

public class TestClass
{
    private readonly IHelloProvider _provider;

    public TestClass(IHelloProvider provider)
    {
        _provider = provider;
    }

    public string Say()
    {
        return _provider.Hello();
    }
}

[TestMethod]
public void WhenSayCallsHelloProviderAndReturnsResult()
{
    //Given
    Mock<IHelloProvider> mock = new Mock<IHelloProvider>();
    TestClass concrete = new TestClass(mock.Object);
    //Expect
    mock.Setup(x => x.Hello()).Returns("Hello World");
    //When
    string result = concrete.Say();
    //Then
    mock.Verify(x => x.Hello(), Times.Exactly(1));
    Assert.AreEqual("Hello World", result);
}

В моем примере я представил интерфейс для IHelloProvider. Вы заметит, что реализация IHelloProvider не реализована. Это лежит в основе того, чего мы пытаемся достичь с помощью решения для насмешек.

Мы пытаемся протестировать класс (TestClass), который зависит от чего-то внешний (IHelloProvider). Если вы используете Test Driven Development, то, возможно, вы еще не написали IHelloProvider, но вы знаете, что он вам понадобится в какой-то момент, хотя вы хотите сначала запустить TestClass, а не отвлекаться. Или, возможно, IHelloProvider использует базу данных, или простой файл, или его сложно настроить.

Даже если у вас полностью работающий IHelloProvider, вы все еще только пытаетесь протестировать поведение TestClass, поэтому с помощью конкретного HelloProvider может сделать ваш тест более склонным к неудаче, Например, если есть изменения в поведении HelloProvider, вам не нужно менять тесты каждого класса, который его использует, вы просто хотите изменить тесты HelloProvider.

Возвращаясь к Теперь у нас есть класс TestClass, который зависит от интерфейса IHelloProvider, реализация которого предоставляется во время построения (это внедрение зависимости).

Поведение Say () заключается в том, что он вызывает Метод Hello () в IHelloProvider.

Если вы оглянетесь назад на тест, мы создали реальный объект TestClass, поскольку мы действительно хотим протестировать код, который мы написали. Мы создали Mock IHelloProvider и сказали, что ожидаем, что у него будет вызван метод Hello (), и когда он это сделает, будет возвращена строка «Hello World».

Затем мы вызываем Say () и проверяем результаты, как и раньше.

Важно понимать, что нас не интересует поведение IHelloProvider, и поэтому мы можем высмеивать его, чтобы упростить тестирование. Нас интересует поведение TestClass, поэтому мы создали реальный TestClass, а не Mock, чтобы мы могли проверить его реальное поведение.

Я надеюсь, что это помогло прояснить, что происходит.

11
ответ дан Modan 12 August 2011 в 06:40
поделиться

Тест не пройдет, если Hello() является внутренним, так как Moq не может обеспечить переопределение метода в этом случае. Это означает, что внутренняя реализация Hello() будет запущена, а не версия для имитации, в результате чего Verify() не будет работать.

Кстати, то, что вы здесь делаете, не имеет смысла в контексте юнит-теста. Юнит-тест не должен беспокоиться о том, что Say() вызывает внутренний метод Hello(). Это реализация внутри вашей сборки, а не код потребления.

.
19
ответ дан 29 November 2019 в 02:16
поделиться

Moq не делает частичного насмехательства и может только насмехаться над публичными виртуальными методами или интерфейсами. Когда вы создаёте Mock, вы создаёте совершенно новую T и удаляете все реализации любых публичных виртуальных методов.

Моим предложением было бы сконцентрироваться на тестировании публичной поверхности ваших объектов, а не их внутренней части. Ваше внутреннее пространство будет покрыто. Просто убедитесь, что у вас есть четкое представление о том, какой ваш целевой класс, и не насмехайтесь над тем, что (в большинстве случаев).

Частичное насмехательство полезно только тогда, когда вы хотите протестировать функциональность абстрактного класса с помощью насмешливых реализаций абстрактных методов. Если Вы этого не делаете, то скорее всего Вы не увидите большой пользы от выполнения частичного насмешка.

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

.
7
ответ дан 29 November 2019 в 02:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: