Удар может функционировать использоваться в различных сценариях?

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

В вашем примере вы вызываете метод 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, чтобы мы могли проверить его реальное поведение.

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

35
задан Herves 19 June 2009 в 05:02
поделиться

2 ответа

Конечно - в вашем скрипте, где вы хотите использовать функцию, вы можете написать команду типа

source function.sh

, которая эквивалентна включению содержимого из function.sh в файле в точке, где выполняется команда. Обратите внимание, что function.sh должен находиться в одном из каталогов в $ PATH ; в противном случае необходимо указать абсолютный путь.

69
ответ дан 27 November 2019 в 06:50
поделиться

Да, вы можете локализовать все свои функции в общем файле (или файлах). Это именно то, что я делаю со всеми своими служебными функциями. В моем домашнем каталоге есть одна utility.shinc , которая используется всеми моими программами с:

. $HOME/utility.shinc

, которая выполняет сценарий в контексте текущей оболочки. Это важно - если вы просто запустите включаемый скрипт, он будет работать в подоболочке, и любые изменения не будут распространяться на текущую оболочку.

Вы можете сделать то же самое для групп скриптов. Если это часть «продукта», я бы старался поместить все сценарии и любые включенные сценарии в один каталог оболочки, чтобы все было локализовано.

11
ответ дан 27 November 2019 в 06:50
поделиться
Другие вопросы по тегам:

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