有两个参数的Controller方法如何写单元测试,需要测试什么场景?
How to write Unit test for Controller method with two parameters and what scenarios are required to test?
我是单元测试的新手。我想为删除控制器操作编写单元测试。我想使用 NSubstitute 来模拟所有依赖项。当前的实现使用接口 IRepository 来抽象出对底层数据源的调用。
控制器
public ActionResult Delete(string fileName, bool isPublic)
{
try
{
repo.DeleteDocument(new PortalDocument
{
Path = fileName,
IsPublic = isPublic
});
}
catch (Exception e)
{
EventLog.Logger.LogCritical(e, e.Message);
}
return RedirectToAction(IndexViewName);
}
存储库接口。
public interface IRepository<out T> where T:
CloudBlobContainer
{
bool DeleteDocument(PortalDocument document);
}
门户文档Class
public class PortalDocument
{
public bool IsPublic { get; set; }
}
提前致谢。
我认为您已经找到了快乐路径方案,即测试没有异常时会发生什么。但是现在你需要测试不愉快的路径,当抛出异常时它的行为是否正确。
//arrange
var mockRepo = new Mock<DocumentRepository>(MockBehavior.Strict);
mockRepo.Setup(r => r.DeleteDocument(It.IsAny<PortalDocument>())).Throws(new Exception("test"));
var controller = new DocumentController(mockRepo.Object);
//act
var result = controller.Delete("filename", true);
//assert
//make sure result is a redirect result
//but how do I test that it got logged?
不幸的是,您会发现您实际上无法测试您是否记录了某些内容。为什么?因为你有一个静态方法调用。静态方法调用不可测试。相反,您应该遵循 dependency inversion principle.
解决此问题的一种方法是用可注入的东西包装您的日志记录调用。
public interface ILogger
{
void LogCritical(Exception exception);
}
public class EventLogLogger : ILogger
{
public void LogCritical(Exception exception)
{
EventLog.Logger.LogCritical(exception, exception.Message);
}
}
那么你的单元测试就变成了:
//arrange
var mockRepo = new Mock<IDocumentRepository>(MockBehavior.Strict);
mockRepo.Setup(r => r.DeleteDocument(It.IsAny<PortalDocument>())).Throws(new Exception("test"));
var mockLogger = new Mock<ILogger>(MockBehavior.Strict);
mockLogger.Setup(l => l.LogCritical(It.IsAny<Exception>())).Verifiable;
var controller = new DocumentController(mockRepo.Object, mockLogger.Object);
//act
var result = controller.Delete("filename", true);
//assert
//make sure result is a redirect result
mockLogger.Verify();
注意,我在示例中使用了 Moq library 语法。您需要根据您的模拟框架进行调整。
如果您是依赖注入的新手,我强烈建议您观看 Deep Dive Into Dependency Injection and Writing Quality Decoupled Code by Miguel Castro。
我是单元测试的新手。我想为删除控制器操作编写单元测试。我想使用 NSubstitute 来模拟所有依赖项。当前的实现使用接口 IRepository 来抽象出对底层数据源的调用。
控制器
public ActionResult Delete(string fileName, bool isPublic)
{
try
{
repo.DeleteDocument(new PortalDocument
{
Path = fileName,
IsPublic = isPublic
});
}
catch (Exception e)
{
EventLog.Logger.LogCritical(e, e.Message);
}
return RedirectToAction(IndexViewName);
}
存储库接口。
public interface IRepository<out T> where T:
CloudBlobContainer
{
bool DeleteDocument(PortalDocument document);
}
门户文档Class
public class PortalDocument
{
public bool IsPublic { get; set; }
}
提前致谢。
我认为您已经找到了快乐路径方案,即测试没有异常时会发生什么。但是现在你需要测试不愉快的路径,当抛出异常时它的行为是否正确。
//arrange
var mockRepo = new Mock<DocumentRepository>(MockBehavior.Strict);
mockRepo.Setup(r => r.DeleteDocument(It.IsAny<PortalDocument>())).Throws(new Exception("test"));
var controller = new DocumentController(mockRepo.Object);
//act
var result = controller.Delete("filename", true);
//assert
//make sure result is a redirect result
//but how do I test that it got logged?
不幸的是,您会发现您实际上无法测试您是否记录了某些内容。为什么?因为你有一个静态方法调用。静态方法调用不可测试。相反,您应该遵循 dependency inversion principle.
解决此问题的一种方法是用可注入的东西包装您的日志记录调用。
public interface ILogger
{
void LogCritical(Exception exception);
}
public class EventLogLogger : ILogger
{
public void LogCritical(Exception exception)
{
EventLog.Logger.LogCritical(exception, exception.Message);
}
}
那么你的单元测试就变成了:
//arrange
var mockRepo = new Mock<IDocumentRepository>(MockBehavior.Strict);
mockRepo.Setup(r => r.DeleteDocument(It.IsAny<PortalDocument>())).Throws(new Exception("test"));
var mockLogger = new Mock<ILogger>(MockBehavior.Strict);
mockLogger.Setup(l => l.LogCritical(It.IsAny<Exception>())).Verifiable;
var controller = new DocumentController(mockRepo.Object, mockLogger.Object);
//act
var result = controller.Delete("filename", true);
//assert
//make sure result is a redirect result
mockLogger.Verify();
注意,我在示例中使用了 Moq library 语法。您需要根据您的模拟框架进行调整。
如果您是依赖注入的新手,我强烈建议您观看 Deep Dive Into Dependency Injection and Writing Quality Decoupled Code by Miguel Castro。