MVC - Moq 单元测试 FileContentResult (ActionResult) - NullRefernceException

MVC - Moq Unit Test FileContentResult (ActionResult) - NullRefernceException

所以我要发布到 MVC 控制器,它调用存储库以获取 Telerik 报告,然后导出 PDF。我在对此进行单元测试时遇到问题并不断收到错误 -

System.NullReferenceException: Object reference not set to an instance of an object.

控制器

public class ReportController : Controller
{
    private IPDFRepository _pdfRepository;

    //Dependency Injection using Unity.MVC5 NuGet Package
    public ReportController(IPDFRepository pdfRepository)
    {
        _pdfRepository = pdfRepository;
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult PDFExport(PDFViewModel model)
    {
        byte[] report = _pdfRepository.BuildExport(model);
        return File(report, "application/pdf", model.SelectedReport + ".pdf");
    }
}

单元测试

[TestMethod]
public void Report_PDFExport_Returns_ActionResult()
{
    //Arrange
    var mockRepository = new Mock<IPDFRepository>();
    mockRepository.Setup(x => x.BuildExport(It.IsAny<PDFViewModel>()));

    ReportController controller = new ReportController(mockRepository.Object);

    //Act
    ActionResult result = controller.PDFExport(It.IsAny<PDFViewModel>());

    //Assert
    Assert.IsInstanceOfType(result, typeof(ActionResult));
}

现在,我意识到这与我控制器的 return 部分有关。

return File(report, "application/pdf", model.SelectedReport + ".pdf");

我可以将其更改为 return 字符串,再次测试并使其正常工作。

此外,如果我注释掉单元测试的最后两行,

//Act
//ActionResult result = controller.PDFExport(It.IsAny<PDFViewModel>());

//Assert
//Assert.IsInstanceOfType(result, typeof(ActionResult));

它将 运行 没有错误。我不知道如何绕过空引用。

您没有正确设置 IPDFRepository 的模拟。当 BuildExport 被调用时,它需要配置 return 的内容。否则 report 将是 null.

而且您也没有使用有效参数调用被测方法。您需要创建一个具体的实例,否则模型将是 nullmodel.SelectedReport,但会出现错误。

[TestMethod]
public void Report_PDFExport_Returns_ActionResult()
{
    //Arrange
    byte[] fakePDFReport = new byte[0];

    var mockRepository = new Mock<IPDFRepository>();
    mockRepository
        .Setup(x => x.BuildExport(It.IsAny<PDFViewModel>()))
        .Returns(fakePDFReport);

    var fakeViewModel = new PDFViewModel {
        SelectedReport = "FakeReportName"
        //Set the needed properties...
    };

    ReportController controller = new ReportController(mockRepository.Object);

    //Act
    ActionResult result = controller.PDFExport(fakeViewModel);

    //Assert
    Assert.IsInstanceOfType(result, typeof(ActionResult));
}