Сбой try/catch блок чтения CSV
Я тестирую свое приложение C#, которое анализирует CSV. Я нахожусь на 94% покрытия кода, потому что я не могу заставить его завершать работу блоков try/catch... Я использую CsvHelper из Nuget http://joshclose.github.io/CsvHelper
public void ParseCsv([FromBody] string csvText)
{
var parseCsv = new XsvData(new[] { "\t", "," });
try
{
using (var reader = new XsvReader(new StringReader(csvText)))
{
parseCsv.Read(reader, headerExists: true);
}
}
catch (Exception)
{
var response = new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent("Unable to read CSV."),
ReasonPhrase = "Invalid CSV"
};
throw new HttpResponseException(response);
}
}
Я попытался передать ему самые непонятные строки, какие только мог придумать, но это проходит через это, и позже появляются ошибки в функции.
[TestMethod]
//[ExpectedException(typeof(HttpResponseException))]
public void TestUploadCsv_UploadingCsvNonCsv()
{
const string csvText = "fhfhk@- jhjfh@ajh- fjkqeqir%hjewq@hf- ujewqh$phfuw \n hfwu- ihfq&if*u@q- afuhwu- fhiue@wfhiuewhiuf";
var context = GetMyFakeEntityDatabase();
var controller = new MyController(context);
controller.ParseCsv(csvText);
}
После блоков try/catch у меня есть раздел, обеспечивающий существование всех заголовков, и он терпит неудачу там, но в этом примере это должно произойти сбой во время чтения. Как заставить мой модульный тест провалиться? Любая помощь приветствуется! Заранее спасибо.
3 ответа
Я решил это, просто передав ему значение null, как рекомендовал Джухарр в комментариях.
Используйте шаблон поставщика и интерфейсы вместо конкретных типов, затем запустите свои модульные тесты, заменив фиктивные объекты, которые будут генерировать исключения.
В деталях:
- Извлечь интерфейс
IXsvReader
отXsvReader
- Внедрить новый конкретный экземпляр
IXsvReader
это бросает исключения наRead
, Создайте один конкретный класс реализации для каждой ошибки, которую вы ожидаете обработать отдельно (в этом случае вам нужна только одна). - В классе, который содержит
ParseCSV
метод, иметь свойство дляIXsvProvider
это устанавливается. В конструкторе этого же класса установите для этого свойства поставщик по умолчанию, который будет возвращать "настоящего" читателя. Этот интерфейс имеет только один метод,GetXsvReader(string text)
- В вашем тестовом классе создайте новый класс с помощью функции ParseCSV, а затем внедрите IXsvProvider(s), который возвращает ваш "фиктивный"
IXsvReader
это просто вызывает исключения всякий раз, когда вы пытаетесь использовать метод.
Вы должны использовать Inversion of Control
и вставьте зависимость в контроллер вместо создания ее в действии контроллера. Таким образом, вы можете издеваться над читателем, и вместо этого выведите исключение.
Я собираюсь написать этот пример с точки зрения CsvHelper
так как это то, что вы говорите, вы используете, хотя пример не похож на это.
Грубо говоря:
public class MyController : Controller
{
private readonly ICsvReader csv;
public MyController( ICsvReader csv )
{
this.csv = csv;
}
}
public class CsvReaderMock : ICsvReader
{
public void Read()
{
throw new Exception();
}
}
Теперь вы можете использовать свой макет ICsvReader
при тестировании, и это вызовет исключение.
Кроме того, вы должны когда-либо тестировать только один метод. Если у вашего метода есть зависимости, вы должны передавать их, а не создавать их, чтобы вы могли тестировать только код в этом методе, а не классы, которые он создает.