2015-12-22 7 views
2

Я хочу знать, есть ли какая-либо лучшая практика в тестировании единиц (C#/NUnit), чтобы протестировать такое решение: Представьте, что у меня есть метод GetOrderById(long orderId) в BLL (Business Logic Layer), который дает мне заказ его ИД :). Поэтому мне нужно написать тест, который будет вызывать этот метод с закодированным Id параметра, но, например, var Id = 1; Если нет записи с таким идентификатором, тест проваливаетсяЛучшая практика тестирования модулей

[Test] 
public void GetOrderById() 
{ 
    //var id = ? 

    Assert.DoesNotThrow(() => { 
     _orderService.GetOrderById(id); 
    }); 
} 

мне нужно какое-то решение, чтобы сделать работу в любое время, создать возможно, временная запись? или smth лучшее решение.

любые идеи?

+0

Если вы являетесь модульным тестированием, вы должны смотреть на использование Injection Dependency, чтобы вы могли создать базу данных макета, которая будет иметь именно те объекты, которые вам нужны. – ChrisF

ответ

1

Так что мне нужно написать тест, который вызовет этот метод с жестким кодом Id, но, например, var Id = 1; Если нет такой записи с идентификатором, тест завершится неудачно

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

У вас BLL должна быть только ссылка на уровень доступа к данным (DAL) через интерфейсы. Он не должен иметь жестко закодированные ссылки на фактически классы. Эти конкретные классы должны поставляться только во время выполнения, путем инъекции. Таким образом, при тестировании вы предоставляете посмеянный DAL, который будет иметь запись с конкретным идентификатором, когда тестирует поставку правильного идентификатора. Аналогичным образом, у него не будет записи с этим идентификатором при тестировании BLL, который правильно обрабатывает отсутствующую запись.

Поскольку DAL высмеивается, он полностью контролируется испытаниями и поэтому легко установить эти условия успеха/сбоя.

0

Для начала вам необходимо реализовать принцип инверсии зависимостей, после чего вы сможете использовать MockObjects через Injection Dependency.

1

Вы не предоставляете много информации о том, что вы хотите достичь с помощью этого теста. Я думаю, вы хотите проверить, может ли метод получить заказ из базы данных. Это, как упоминает Дэвид Арно, интеграционное тестирование. В общем, тестирование против базы данных или файловой системы плохое и делает для медленных и хрупких тестов. Если вы отделили свой уровень доступа к данным с бизнес-слоем с помощью интерфейса, вы можете использовать Subsititue (в nUnit lib) и предоставить его вашему уровню.

Fx:

IDataAccess interfaceStub = Substitute.For<IDataAccess>(); 

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

Может быть что-то вроде этого:

//A few simple tests 
    [TestMethod] 
    public void CheckThatOrderExist() 
    { 
     var service = new OrderServiceTestable(); 
     var order = service.GetOrderById(1);//This will be found in the list 
     Assert.IsNotNull(order); 
    } 

    [TestMethod] 
    public void CheckThatOrderDoesNotExist() 
    { 
     var service = new OrderServiceTestable(); 
     var order = service.GetOrderById(2);//This will not be found 
     Assert.IsNull(order); 
    } 

    //Your data access layer 
    public class OrderService 
    { 
     protected virtual IList<Order> OrderList { get; set; } 

     public Order GetOrderById(int id) 
     { 
      return OrderList.SingleOrDefault(x => x.Id == id); 
     } 
    } 

    //Order object 
    public class Order 
    { 
     public int Id { get; set; } 
    } 

    //This class inherits the order service and over write the list of orders. An instance of this class is used in the tests. 
    public class OrderServiceTestable : OrderService 
    { 
     protected new List<Order> OrderList; 

     public OrderServiceTestable() 
     { 
      OrderList = new List<Order> {new Order {Id = 1}}; //This will overwrite the list of orders because its virtual in the order service class 
     } 
    } 

Посмотрите, что я сделал? Наследуя действительный класс и переписывая свойства или методы, которые являются виртуальными. Вы можете сделать свою тестовую возможность перезаписывать любые данные, в то же время вы можете проверить фактический метод в классе OrderService. Это обеспечит надежные и ослепительно быстрые тесты. Вы не проверяете свой уровень доступа к данным, а только метод на вашем бизнес-уровне. Однако может потребоваться некоторая работа с вашей стороны.

С этим утверждением я по-прежнему рекомендую развязать интерфейсы.