2015-04-06 4 views
0

Я новичок в модульном тестировании, поэтому простите меня, если я не смогу правильно объяснить этот вопрос. Я читаю книгу «Искусство модульного тестирования второго издания» и пытаюсь реализовать модульное тестирование в моем проекте. В настоящее время я застрял или запутался при тестировании, используя насмешку (используя NSubstitute в качестве насмешливой структуры).Использование Nsubstitute для насмешек, но получение ошибки

Вот мой сценарий:

У меня есть два интерфейса ICommand и IUser

public interface ICommand 
{ 
     string execute(); 
} 

public interface IUserCalendar 
{ 
    string LoadCalendar(); 
} 

У меня есть класс, который реализует LoadCalendarICommand:

public class LoadCalendar : ICommand 
{ 
    private IUserCalendar user; 

     public string execute() 
     { 
      return this.user.LoadCalendar(); 
     } 

     public LoadCalendar(IUserCalendar obj) 
     { 
      this.user = obj; 
     } 
} 

ViewCalendarIUserCalendar реализует:

public class Viewer : IUserCalendar 
{  
     public string LoadCalendar() 
     { 
      return "Viewer Load Calendar Called"; 
     } 
} 

Использование класса агента Я вызываю команду для конкретного запроса. (Здесь я показываю только один запрос LoadCalendar для одного пользователя, но у меня больше команд и больше пользователей)

Мой клиент имеет объект invoker, который вызывает команду для конкретного пользователя.

public class Client 
{  
     public Client() 
     { } 

     public string LoadCalendar(ICommand cmd) 
     { 
      Invoker invoker = new Invoker(cmd); 
      return invoker.execute(); 
     }  
} 

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

[Test] 
public void client_Load_Calendar_Administrator() 
{ 
      IUserCalendar calanedar = Substitute.For<IUserCalendar>(); 
      ICommand cmd = Substitute.For<ICommand>(calanedar); 

      Client c = new Client(); 
      c.LoadCalendar(cmd, calanedar).Returns(Arg.Any<string>()); 
} 

Я не знаю, где я делаю неправильно, и это ошибка.

NSubstitute.Exceptions.SubstituteException: Невозможно предоставить аргументы конструктора при замене интерфейса.

Любая помощь действительно оценена. Извините за длинный вопрос.

+0

Спасибо за редактирование Марка. Если вы знаете любого, кто может ответить на этот вопрос, пожалуйста, отправляйте его. – fais

ответ

2

Ошибка вы получаете:

не может предоставить аргументы конструктора при замене для интерфейса.

Сообщает вам, что именно не так.

можно передать в качестве аргументов конструктора здесь:

ICommand cmd = Substitute.For<ICommand>(calanedar); 

Конечно, интерфейсы никогда не конструктор. Вы пытаетесь взаимодействовать с интерфейсом ICommand, как если бы это была ваша конкретная реализация LoadCalendar.

Кроме того, чтобы иметь возможность тестировать класс, вы всегда хотите иметь конструктор по умолчанию (без параметров). На самом деле многие из насмешливые рамки требуют этого.

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

Либо это, либо вы заменяете только ICommand, чтобы вернуть его предварительно заданное (строковое) значение. Затем вы можете проверить, действительно ли код, который потребляет вашу команду, вызывает его и/или делает правильную вещь с возвращаемым значением.

Для иллюстрации:

[Test] 
public void client_Load_Calendar_Administrator() 
{ 
    // You are substituting (mocking) the IUserCalendar here, so to test your command 
    // use the actual implementation 
    IUserCalendar calendar = Substitute.For<IUserCalendar>(); 

    ICommand cmd = new LoadCalendar(calendar): 

    // Let the IUserCalendar.LoadCalendar() return a certain string 
    // Then Assert/Verify that cmd.Execute() returns that same string 
} 

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

Чтобы проверить клиента:

[Test] 
public void client_Load_Calendar_Administrator() 
{ 
    ICommand cmd = Substitute.For<ICommand>(); 

    Client c = new Client(); 
    // Let your command return a certain string 
    // Then verify that your calendar returns that same string 
} 

EDIT: В случае, если вы заинтересованы, the method in NSubstitute that throws this exception:

private void VerifyNoConstructorArgumentsGivenForInterface(object[] constructorArguments) 
{ 
    if (constructorArguments != null && constructorArguments.Length > 0) 
    { 
     throw new SubstituteException("Can not provide constructor arguments when substituting for an interface."); 
    } 
} 

они не очень ясно об этом: никаких аргументов конструктора для интерфейса замените, несмотря ни на что.

+0

Можете ли вы предоставить мне более подробную информацию об Интеграционном Тестировании? Любая ссылка или любая справочная книга действительно оценена – fais

+0

Эта ссылка может быть вам интересна: http://stackoverflow.com/questions/5357601/whats-the-difference-between-unit-tests-and-integration-tests. Извините, что я не мог предоставить вам пример рабочего кода - я не знаком с NSubstitute, я лично использую Moq. Поэтому я не знаю точной семантики того, как выполнить то, что я пытаюсь объяснить. Я могу предоставить более полный пример, сделанный с помощью Moq и XUnit, если вам нравится? –

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