2014-01-21 3 views
0

У меня есть простой метод «Получить». Пример:Единичный тест не будет «покрывать» простой метод получения. (C#)

public class Foo : IFoo 
{ 
    public Dictionary<string,string> GetSomething(string xyz) 
    { 
     var result = new Dictionary<string,string> 
     ... Go to DB and return some key value pairs 
     return result; 
    } 
} 

Я написал простой тест, который выполняется и успешно проходит, но я не получаю покрытие кода по методу.

[TestMethod()] 
    public void GetSomething() 
    { 
     var target = new StubIFoo(); 

     var expected = new Dictionary<string, string> 
     { 
      {"blahKey","blahValue"} 
     }; 

     var results = target.GetSomethingString = s => 
     { 
      var result = new Dictionary<string, string> {{"a", "b"}}; 
      return result; 
     }; 

     var actual = results("a"); 

     CollectionAssert.AreEqual(expected,actual); 
    } 

Я также попытался предназначаться самого класса, который обеспечивает покрытие, но не возвращает никаких результатов (например: «вар цель = новый StubFoo();»)

Опять же, он успешно выполняет и проходит, но я не получаю никакого покрытия. Любые указатели будут оценены. Благодарю.

+0

Какое покрытие вы ожидаете? Какова связь между «StubFoo» и «Foo»? – Paolo

+0

Что вы пытаетесь проверить? 'Foo' или что-то еще? Если вы пытаетесь протестировать 'Foo', почему вы заканчиваете' GetSomething'? (В принципе, вы не можете ожидать покрытия по методу, который вы намеренно выполняете - вы не выполняете этот код!) –

+0

Показать код для ваших заглушек. – Haney

ответ

0

В вашем тесте вы не вызываете метод GetSomething, но вместо этого устанавливаете значение для свойства GetSomethingString.

// Here is the problem. This: 
var results = target.GetSomethingString = s => 
{ 
    var result = new Dictionary<string, string> {{"a", "b"}}; 
    return result; 
}; 
// Is equal to this: 
var lambda = s => 
{ 
    var result = new Dictionary<string, string> {{"a", "b"}}; 
    return result; 
}; 
var results2 = target.GetSomethingString = lambda; 
+0

Я изменил его до моего первоначального теста, но пока он покрывает код, фактический ничего не возвращает (пытается избежать зависимости db). var target = new StubFoo(); var expected = new Словарь <строка, строка> { {"a", "b"} }; var actual = target.GetSomething ("a"); CollectionAssert.AreEqual (ожидается, актуально); – user3219570

2

Foo.GetSomething() имеет 0 охват кода, потому что вы никогда не называете его в своем тесте. Вместо этого вы вызываете StubIFoo.GetSomething().

Измените var target = new StubIFoo(); на var target = new Foo();, удалите код, инициализирующий StubIFoo, и вы получите некоторое покрытие.

Заготовки для предотвращения использования (и тестирования) настоящего класса. Но вы не должны использовать заглушку класса, который вы тестируете!

+0

Спасибо. У меня было это изначально, но я не мог понять, как удалить зависимость db. Похоже, мне нужно будет заглушить «GetSomething» и «закрепить» вызов БД. – user3219570

+0

Если вы хотите удалить зависимость базы данных, вам необходимо заглушить классы DB (IDbConnection, IDbCommand ...) или для вашего уровня БД, который вы используете в методе Foo.GetSomething(). Для этого вы можете, например, использовать инъекцию зависимостей (короче говоря, когда в вашей программе вы хотите IDbConnection, она дает вам SqlConnection и когда вы хотите IDbConnection в своем тесте, это дает вам StubIDbConnection) – krimog

+0

@ user3219570: Вам не нужно заглушать Foo, но сведение вызова DB должно работать. Однако это может быть грязно. Вы, вероятно, должны делать то, что предлагает кримог. – Magus

0

Вот общая идея, что вы должны сделать

public class Foo : IFoo 
{ 
    IDbAccess db; 

    // Pass the interface, do pass parameters to create it inside constructor 
    public Foo(IDbAccess db) 
    { 
     this.db = db; 
    } 

    public Dictionary<string,string> GetSomething(string xyz) 
    { 
     var result = new Dictionary<string,string> 

     // ... Go to DB and return some key value pairs 
     result.Add(db.MethodWhatever(xyz)); 

     return result; 
    } 
} 

[TestMethod()] 
public void GetSomething() 
{ 
    var dbMock = new DatabaseMock(); // This implements IDbAccess 
    var target = new Foo(dbMock); 

    var expected = new Dictionary<string, string> 
    { 
     {"blahKey","blahValue"} 
    }; 

    // get something 
    var results = target.GetSomething("xyzstring"); 

    // verify results 
    var actual = results.whatever; 

    CollectionAssert.AreEqual(expected,actual); 
} 
+0

Эй, Янне, я ценю ваше время и быстрый ответ.Я не уверен, что знаю, как «заглушить/издеваться» IDbCommand (я предполагаю, что ваш IDbAccess - это интерфейс, наследующий от него), не реализуя всех его членов. – user3219570

+0

Вы не заглушите/mock IDbCommand. Вы просто создаете интерфейс, чтобы вы могли создавать макетный объект, чтобы действовать как доступ к базе данных. Как и ваш фактический экземпляр db, также следует реализовать интерфейс IDbAccess с сохранением в качестве DatabaseMock, который будет просто возвращать данные, за исключением. Если Foo.GetSomething создаст DbCommand и выполнит его, вам нужно избавиться от зависимостей, отредактировав его так, чтобы у вас был класс, который будет реализовывать нужные вам методы dataacceess. –

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