2009-09-23 1 views
0

У меня есть следующий код (упрощенный).Как издеваться над вызовом метода из другого класса в Rhino Mock AAA?

public class OrderProcessor 
{ 
    public virtual string PlaceOrder(string test) 
    { 
     OrderParser orderParser = new OrderParser(); 
     string tester = orderParser.ParseOrder(test); 
     return tester + " here" ; 
    } 

} 

public class OrderParser 
{ 

    public virtual string ParseOrder(string test) 
    { 
     if (!string.IsNullOrEmpty(test.Trim())) 
     { 
      if (test == "Test1") 
       return "Test1"; 
      else 
      { 
       return "Hello"; 
      } 
     } 
     else 
      return null; 
    } 
} 

Мой тест выглядит следующим образом -

public class OrderTest 
    { 
     public void TestParser() 
     { 
     // Arrange 

     var client = MockRepository.GenerateMock<OrderProcessor>(); 
     var spec = MockRepository.GenerateStub<OrderParser>(); 

     spec.Stub(x => x.ParseOrder("test")).IgnoreArguments().Return("Test1"); 

     //How to pass spec to client so that it uses the same. 

     } 
    } 

Теперь как я могу проверить клиента так, что он использует метод высмеивал от OrderParser. Я могу издеваться над OrderParser, но как передать это в orderProcessor mocked class?

Пожалуйста, дайте мне знать.

Заранее спасибо.

ответ

1

Я немного смущен вашим тестом, так как вы на самом деле ничего не проверяете, кроме того, что RhinoMocks работает. Вы создаете два макета, а затем делаете некоторые утверждения на них. Вы даже не проверили свои настоящие классы.

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

Start путем извлечения интерфейса из вашего класса OrderParser:

public interface IOrderParser 
{ 
    String ParseOrder(String value); 
} 

Теперь убедитесь, что ваш класс OrderParser реализует этот интерфейс:

public class OrderParser: IOrderParser{ ... } 

Теперь вы можете реорганизовать класс OrderProcessor принять в случае, объекта IOrderParser через его конструктор. Таким образом, вы «вводите» зависимость в класс.

public class OrderProcessor 
{ 
    IOrderParser _orderParser; 

    public OrderProcessor(IOrderParser orderParser) 
    { 
     _orderParser = orderParser; 
    } 

    public virtual string PlaceOrder(string val) 
    { 
     string tester = _orderParser.ParseOrder(val); 
     return tester + " here" ; 
    } 
} 

В вашем тесте вы хотите только высмеять зависимость, а не SUT (Subject Under Test). Ваш тест будет выглядеть примерно так:

public class OrderTest 
    { 
     public void TestParser() 
     { 
     // Arrange 

     var spec = MockRepository.GenerateMock<IOrderParser>(); 
     var client = new OrderProcessor(spec); 

     spec.Stub(x => x.ParseOrder("test")).IgnoreArguments().Return("Test1"); 

     //Act 
     var s = client.PlaceOrder("Blah"); 

     //Assert 
     Assert.AreEqual("Test1 Here", s); 

     } 
    } 

Это трудно для меня, чтобы оценить то, что вы пытаетесь сделать с вашими классами, но вы должны быть в состоянии получить представление от этого. Несколько аксиом следовать:

  1. использовать интерфейсы и состав над наследованием
  2. Использованием dependency injection для внешних зависимостей (инверсии управления)
  3. Test единого целого, и имитационных его зависимостями
  4. Mock только один уровня зависимостей. Если вы тестируете класс X, который зависит от Y, которая зависит от Z, вы только должны быть насмешливым Y и никогда Z.
  5. Всегда test behavior и никогда детали реализации

Вы, кажется, на правильном пути, но нужно небольшое руководство. Я бы посоветовал прочитать материал, который Martin Fowler, и Bob Martin должны подняться до скорости.

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