为了账号安全,请及时绑定邮箱和手机立即绑定

如何为带有两个参数的Controller方法编写单元测试以及需要测试哪些场景?

如何为带有两个参数的Controller方法编写单元测试以及需要测试哪些场景?

C#
慕尼黑8549860 2021-06-03 18:01:03
我是单元测试的新手。我想为删除控制器操作编写单元测试。我想使用 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);}门户文档类public class PortalDocument{    public bool IsPublic { get; set; }}提前致谢。
查看完整描述

1 回答

?
人到中年有点甜

TA贡献1895条经验 获得超7个赞

我想你已经找到了快乐路径场景,测试在没有例外的情况下会发生什么。但是现在您需要测试不愉快的路径,当抛出异常时它的行为是否正确。


//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?

不幸的是,您会发现您实际上无法测试您是否记录了某些内容。为什么?因为你有一个静态方法调用。静态方法调用不可测试。相反,您应该遵循依赖倒置原则。


解决此问题的一种方法是用可注入的东西包装您的日志记录调用。


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 库语法。您需要根据您的模拟框架进行调整。


如果您不熟悉依赖注入,我强烈建议您观看Miguel Castro 的 Deep Dive Into Dependency Injection 和 Writing Quality Decoupled Code。



查看完整回答
反对 回复 2021-06-05
  • 1 回答
  • 0 关注
  • 217 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信