2015-07-08 2 views
1

Я новичок в nSubstitute. Я видел примеры кода, подобные этому во многих статьях. Что такое тестирование интерфейса? Когда закончится следующий тест? Не сработает ли следующий тест на основе фактической реализации IMathService? Идея здесь состоит в том, чтобы написать это сначала в TDD, а затем удалить замену и поставить реальную реализацию? Или идея состоит в том, чтобы протестировать некоторую реальную реализацию, но замените зависимости на Nsubstitute? Если да, этот пример не показывает этого. Я смущен.Какая польза от тестирования интерфейса, а не от реализации?

public interface IMathService 
{ 
    int Add(int a, int b); 
} 

[Test] 
public void nSubstituteMockingInterface() 
{ 
    var mathService = Substitute.For<IMathService>(); 
    mathService.Add(2,3).Returns(4); 
    Assert.IsTrue(mathService.Add(2, 3) == 4); 
} 

Предположим, у меня есть следующая реализация, будет ли вышеописанный тест терпеть неудачу? Линия Substitute.For() вернет экземпляр MyMathService? Полагаю, это не так. Если да, то что произойдет, если у меня есть более чем одна реализация для IMathService

class MyMathService: IMathService 
{ 
    public int Add(int a, int b) 
    { 
     throw new Exception("error"); 
    } 
} 

ответ

2

Вы совершенно правы, эти фрагменты не как вы обычно используете рамки изоляции. Это примеры использования, которые показывают, как использовать библиотеку nSubsitute. В вашем примере тест пройдет, потому что он использует динамически сгенерированный объект, который придерживается интерфейса IMathService, но запрограммирован на возврат 4, когда его метод Add вызывается с аргументами 2 и 3. Реальная реализация не используется нигде в этом контрольная работа.

nSubstitute и его альтернативы могут использоваться для тестирования взаимодействия класса и его сотрудников. Вы используете эти изоляционные рамки для тестирования классов по отдельности. Как правило, вы создаете конкретный экземпляр System Under Test (SUT), но предоставляете поддельные реализации для своих сотрудников. Затем вы можете установить ожидания для поддельных соавторов или утверждать, что на них были вызваны определенные методы, чтобы убедиться, что SUT правильно взаимодействует со своими сотрудниками. Вместо того, чтобы вручную раскручивать собственные поддельные коллабораторы, вы можете использовать среду изоляции для автоматизации этой повторяющейся работы для вас.

Пример, надеюсь, делает вещи более ясными. Предположим, я работаю над классом Foo, и я использую IBAR-совместителя, которого я еще не реализовал. IBar будет говорить с реальной базой данных, так что я не хочу использовать реальное осуществление IBar в моих изолированных модульных тестов для Foo:

public class Foo 
{ 
    private readonly IBar _bar; 

    public Foo(IBar bar) 
    { 
     _bar = bar; 
    } 

    public void DoSomething() 
    { 
     _bar.DoSomethingElse(); 
    } 
} 

public interface IBar 
{ 
    void DoSomethingElse(); 
} 

public class AnImplementationOfBar : IBar 
{ 
    public void DoSomethingElse() 
    { 
     throw new System.NotImplementedException(); 
    } 
} 

[Test] 
public void Foo_interacts_correctly_with_its_bar() 
{ 
    var fakeBar = Substitute.For<IBar>(); 
    var foo = new Foo(fakeBar); 

    foo.DoSomething(); 

    fakeBar.Received().DoSomethingElse(); //This is the assertion of the test and verifies whether fakeBar.DoSomethingElse has been called. 
} 

public static void Main(string[] args) 
{ 
    //Production code would look like this: 
    var foo = new Foo(new AnImplementationOfBar()); 
    //next line throws because AnImplementationOfBar.DoSomethingElse has not been implemented yet 
    foo.DoSomething(); 
} 

Замены могут быть использованы в примерно два сценария:

  1. Чтобы проверить, произошло ли правильное взаимодействие (например, пример кода из моего ответа выше, используя метод Received()). Как правило, слово mock используется для подделок с этой целью.
  2. Чтобы предоставить фиктивные данные SUT, чтобы производственный код выполнял определенный путь кода. Обычно для такого рода подделок используется слово stub. Тест IMathService является типичным примером того, как вы должны настроить заглушку с помощью метода Returns().

Если вы знакомы с определением Устройте-Act-Assert для модульных тестов: Столбики являются часть Устройте фазу теста, так как они создали фиктивные данные, которые требуют вашего SUT. Mocks являются частью части Assert, поскольку вы используете их для проверки того, произошло ли определенное взаимодействие.

Этот метод используется в определенном стиле Test-Driven Development, который называется наружным - в TDD (также называемом London School TDD). Это позволяет вам полностью реализовать класс и указать контракты для своих сотрудников без фактического внедрения самих соавторов, а просто создания интерфейсов.Его также можно использовать в других сценариях, например, когда вы тестируете устройство и не хотите работать с реальной базой данных, сетевым трафиком, зависимым от третьей стороны и/или классом, который просто ужасно трудный или медленный в использовании тесты.

Для получения дополнительной информации по этим темам, отметьте сообщение Мартина Фаулера на странице Mocks Aren't Stubs.