我正在尝试对抛出异常的方法进行单元测试,并且在抛出之前必须执行一些任务,例如日志记录。我正在使用NSubstitute
而无法理解这一点。
所以我的测试看起来像这样
[TestMethod]
[ExpectedException(typeof(IOException))]
public void RecordAnalyser_FileReadFailedInFirstAttempt_WarningLogged()
{
//Arrange
var fileMock = Substitute.For<IFile>();
fileMock.ReadLines(Arg.Any<string>()).Throws(new IOException());
//Act
var recordAnalyser = new RecordAnalyser(fileMock, logger); //--> throws exception.
//Assert
logger.Received(1).Warn(Arg.Any<string>(), Arg.Any<Exception>());
}
现在我想断言如果logger收到警告日志,但由于上面的行发送了一个异常,并且我有一个预期的异常属性,test不会检查断言。
我能想到的一个脏代码是将错误语句包装在测试中的try catch中,但它不是最好的。
//Act
try
{
var recordAnalyser = new RecordAnalyser(fileMock, logger);
}
catch (Exception)
{
// eat
}
正在测试的代码 -
public RecordAnalyser(IFile file, ILoggerService logger)
{
this.logger = logger;
try
{
names = file.ReadLines(Constants.Names).ToList();
}
catch (System.IO.IOException e)
{
logger.Error("Names file could not be read.", ex);
// How do I test above line without a try catch block in unit test
throw;
}
}
在这里寻找建议。
答案 0 :(得分:2)
这可能是XY problem。
您正尝试在一次测试中测试/断言多项内容。因此问题。
如果目标仅仅是为了测试异常被抛出那么很好,没有尝试/ catch和测试会通过。
[TestMethod]
[ExpectedException(typeof(IOException))]
public void RecordAnalyser_Should_FailInFirstAttempt_When_FileRead() {
//Arrange
var fileMock = Substitute.For<IFile>();
fileMock.ReadLines(Arg.Any<string>()).Throws(new IOException());
//Act
var recordAnalyser = new RecordAnalyser(fileMock, logger); //--> throws exception.
}
在另一个测试中,如果要在抛出异常时声明某些事情发生,那么您需要捕获异常以允许执行测试以完成测试并允许验证断言。
[TestMethod]
public void RecordAnalyser_Should_LogWarning_When_FileReadFailedInFirstAttempt() {
//Arrange
var fileMock = Substitute.For<IFile>();
fileMock.ReadLines(Arg.Any<string>()).Throws(new IOException());
IOException error = null;
//Act
try {
var recordAnalyser = new RecordAnalyser(fileMock, logger); //--> throws exception.
} catch(IOException ex) {
error = ex; //catch and hold error for later
}
//Assert
if(error == null)
Assert.Failed("exception expected"); // error was not thrown.
logger.Received(1).Warn(Arg.Any<string>(), Arg.Any<Exception>());
}
答案 1 :(得分:0)
您可以使用以下Extension来提供Assert.Throws(Action)和Assert.Throws(Action)的实现:https://github.com/bbraithwaite/MSTestExtensions