2014-10-01 74 views
2

我正在测试解析CSV的C#应用​​程序的单元测试。我在94%的代码覆盖率,因为我不能强迫它失败try/catch块......我使用CsvHelper从的NuGet http://joshclose.github.io/CsvHelper失败try/catch块读取csv

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 = "[email protected] [email protected] fjkqeqir%[email protected] ujewqh$phfuw \n hfwu- ihfq&if*[email protected] afuhwu- [email protected]"; 
    var context = GetMyFakeEntityDatabase(); 
    var controller = new MyController(context); 
    controller.ParseCsv(csvText); 
} 

的try/catch块后,我有一个强制的所有头存在的部分,它在那里失败了,但是在这个例子中,它在阅读过程中应该失败。我如何强制我的单元测试失败?任何帮助表示赞赏!提前致谢。

+0

+1用于测试代码如何处理失败。 – 2014-10-01 15:59:55

+1

您可以将'null'传递给'csvText'。 – juharr 2014-10-01 16:01:14

+0

@juharr它目前的写法,可以工作,但它不是一个非常通用的解决方案。如果他想要空/空字符串与无效语法的不同状态代码会怎样。 – 2014-10-01 16:08:45

回答

0

我解决了这个问题,只是将它传递给null,就像评论中推荐的juharr一样。

0

使用提供者模式和接口,而不是具体类型,然后运行你的单元测试,通过代替抛出异常的模拟对象。

详细:

  • 提取接口IXsvReaderXsvReader
  • 实施的IXsvReader一个新的具体实例上Read抛出异常。为每个你希望单独处理的错误创建一个具体的实现类(在这种情况下,你只需要一个)。
  • 在包含ParseCSV方法的类中,具有可设置的IXsvProvider的属性。在该类的构造函数中,将该属性设置为将返回“真实”读者的默认提供者。这个接口只有一个方法,GetXsvReader(string text)
  • 在你的测试类中,用ParseCSV函数新建类,然后注入一个IXsvProvider,它返回你的“dummy”IXsvReader,只要你试图使用方法。
0

您应该使用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测试时,它会抛出异常。

此外,你应该只测试一种方法。如果你的方法具有依赖性,你应该传递它们而不是创建它们,所以你只能测试该方法中的代码,而不能测试它创建的类。