2016-12-16 9 views
3

У меня есть класс Person и интерфейс:Запись C тест # NUnit, не имея доступа к остальной части кода

interface IService 
{ 
    double GetAccDetails(int personId); 
} 

public class Person 
{ 
    private int _personId; 
    private IService _service; 

    public Person(int personId, IService service) 
    { 
     _personId= personId; 
     _service = service; 
    } 

    public double Amount {get; set;} 

    public void UpdateBackingAcc() 
    { 
     Amount = _service.GetAccDetails(_personId); 
    } 
} 

И я должен покрыть этот кусок кода с NUnit тестов, однако я не» t иметь доступ к службе, но только к коду, который я опубликовал.

Так что мои вопросы:

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

  2. Какие тесты могут быть созданы для данного интерфейса? Я предполагаю, что один из тестов может попытаться использовать personId1 и получить статическое значение, тогда он может использовать personId2 и может получить другое значение, а затем проверить, была ли эта сумма обновлена ​​или нет. Поэтому, если это правильно, это может быть всего лишь 1 единичный тест.

Возможно, имеет смысл проверить, если значение отрицательное или нет ... может быть также значение 0 ...

Любые другие идеи?

ответ

2

Ваш класс Person имеет открытый конструктор, общедоступный метод get \ set и общедоступный метод. Рекомендация - проверить открытый интерфейс класса. Для вас класс вы можете испытать:

  1. Ctor, вы должны подтвердить, что IService против null. Улучшите свой код, чтобы проверить это.
  2. Вы можете проверить свои свойства получить и установить
  3. Вы можете проверить, когда UpdateBackingAcc называется, что IService будет вызван, и значение будет сохранено в Amount собственности.
1

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

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

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

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

1

1/Да, сервис является внешней зависимостью тестируемого класса, и его следует издеваться.

2/Интерфейс не может быть протестирован, так как у него нет кода. Класс человека может быть протестирован.

Я согласен с тобой. Здесь вы можете проверить constructor и доказать, что поля были установлены правильно.Но только разумный тест, который я могу сделать, - это следующий тест. Он проверяет, что Amount содержит значение, возвращаемое службой после того, как был выполнен метод UpdateBackingAcc.

[TestMethod] 
public void UpdateBackingAcc_WhenCalled_AmountContainsValueReturnedFromService() 
{ 
    Mock<IService> serviceMock = new Mock<IService>(); 
    const double expectedResult = 100; 
    const int personId = 200; 
    serviceMock.Setup(s => s.GetAccDetails(It.Is<int>(id => id == personId))) 
     .Returns(() => expectedResult); 
    Person person = new Person(personId, serviceMock.Object); 

    // Act 
    person.UpdateBackingAcc(); 

    // Assert 
    double actualResult = person.Amount; 
    Assert.AreEqual(expectedResult, actualResult); 
} 

Здесь мы не располагаем всей информацией об услуге. Например. что возвращает сервис при вызове с недопустимым personId? Учитывая это, можно было бы написать несколько тестов, например.

  • UpdateBackingAcc_PersoneIdValid_AmountContainsValueReturnedFromService
  • UpdateBackingAcc_PersoneIdInvalid_ThrowsException

[TestMethod] 
[ExpectedException(typeof(InvalidOperationException))] 
public void UpdateBackingAcc_PersoneIdInvalid_ThrowsException() 
{ 
    // Arrange 
    Mock<IService> serviceMock = new Mock<IService>(); 
    const int invalidPersonId = -1; 
    serviceMock.Setup(s => s.GetAccDetails(It.Is<int>(i => i == invalidPersonId))) 
     .Throws<InvalidOperationException>(); 
    Person person = new Person(invalidPersonId, serviceMock.Object); 

    // Act 
    person.UpdateBackingAcc(); 

    // Assert 
    // Throws exception 
} 
+0

Я думаю, что 'Броски exception' не ответственность' класса Person'. – Fabio

+0

@Fabio вы абсолютно правы! Я попытался теоретически рассмотреть возможность, когда служба получает недопустимое значение Id и выбрасывает исключение. См. Отредактированный ответ. – dee

+0

Нет @dee, я хочу сказать, что вам вообще не нужно 'try .. catch'. И, конечно, вам не нужно его проверять. Если сервис бросит, бросьте его. – Fabio

 Смежные вопросы

  • Нет связанных вопросов^_^