单元测试Server.MapPath(),用于根据HTML模板发送电子邮件

时间:2016-11-17 12:53:47

标签: c# asp.net-mvc unit-testing mstest

我正在尝试对基于HTML模板异步向用户发送电子邮件的Api控制器进行单元测试。

控制器操作:

    public async Task<IHttpActionResult> Email(int id)
    {
        var company = _unitOfWork.Companies.GetCompany();

        var repairTypes = _unitOfWork.RepairTypes.GetRepairTypes().ToList();

        var repair = _unitOfWork.Repairs.GetRepair(id);

        if (repair == null || company == null || !repairTypes.Any() || !repair.Devices.Any())
            return NotFound();

        if (repair.Customer.Email == null)
        {
            return BadRequest("No customer email");
        }
        try
        {
            var viewModel = new ReceiptViewModel(company, repair, false, false);

            viewModel.AssignRepairTypes(repairTypes);

            await Core.Utilities.Email
                .SendEmail(repair.Customer.Email, viewModel.GetReceiptEmailBody(), "Your Repair Summary");
        }
        catch (Exception exception)
        {
            return BadRequest(exception.Message);
        }
        return Ok();
    }

查看从磁盘读取模板的模型:

public class ReceiptViewModel
{
    public Company Company { get; set; }
    public Repair Repair { get; }
    public bool ShowLogo { get; private set; }
    public bool AutoPrint { get; private set; }

    public ReceiptViewModel(Company company, Repair repair, bool showLogo, bool autoPrint)
    {
        Company = company;
        Repair = repair;
        ShowLogo = showLogo;
        AutoPrint = autoPrint;

        if (Company.LogoPath.Contains("~"))
        {
            Company.LogoPath = Company.LogoPath.Remove(0, 1);
        }
    }

    public void AssignRepairTypes(IEnumerable<RepairType> repairTypes)
    {
        Repair.Devices.ForEach(d => d.RepairType =
            repairTypes.SingleOrDefault(rt => rt.Id == d.RepairTypeId));
    }

    public string GetReceiptEmailBody()
    {
        var server = HttpContext.Current.Server;

        // Generate the email body from the template file.
        var emailHtmlBody = new TemplateService();

        var path = server.MapPath("~/Views/Repairs/ReceiptTemplate.cshtml");

        var readAllText = File.ReadAllText(path);

        return emailHtmlBody.Parse(readAllText, this, null, "RepairEmail");
    }
}

测试类:

[TestClass]
public class RepairsControllerTests
{
    private RepairsController _controller;
    private Mock<ICompanyRepository> _mockCompanyRepository;
    private Mock<IRepairRepository> _mockRepairRepository;
    private Mock<IRepairTypeRepository> _mockRepairTypeRepository;

    [ClassInitialize]
    public static void Init(TestContext context)
    {
        Mapper.Initialize(c => c.AddProfile<MappingProfile>());
    }

    [TestInitialize]
    public void TestInitialize()
    {

        HttpContext.Current = new HttpContext(new HttpRequest(null, "http://test.org", null), new HttpResponse(null));

        _mockCompanyRepository = new Mock<ICompanyRepository>();
        _mockRepairRepository = new Mock<IRepairRepository>();
        _mockRepairTypeRepository = new Mock<IRepairTypeRepository>();

        var mockUoW = new Mock<IUnitOfWork>();

        mockUoW.SetupGet(u => u.Companies).Returns(_mockCompanyRepository.Object);
        mockUoW.SetupGet(u => u.Repairs).Returns(_mockRepairRepository.Object);
        mockUoW.SetupGet(u => u.RepairTypes).Returns(_mockRepairTypeRepository.Object);

        _controller = new RepairsController(mockUoW.Object);

        _controller.MockCurrentUser("1", "user1@domain.com");
    }


//All other tests..

    [TestMethod]
    public async Task Email_ValidRequest_ShouldReturnOk()
    {
        var company = new Company() { Name = "Test", Email = "a@a.com", Id = 1, City = "T", Country = "C", LogoPath = "", PhoneNumber = "", PostCode = "", Street = "", TnC = "" };
        var repairTypes = new List<RepairType>() { new RepairType() { Id = 1, Name = "Test" } };
        var devices = new List<Device>() { new Device() { Id = 1, SerialNumber = "1", RepairTypeId = 1 } };
        var repair = new Repair
        {
            Id = 1,
            Customer = new Customer() { Email = "test@tm.com" },
            Devices = devices
        };

        _mockRepairRepository.Setup(r => r.GetRepair(1)).Returns(repair);
        _mockCompanyRepository.Setup(r => r.GetCompany()).Returns(company);
        _mockRepairTypeRepository.Setup(r => r.GetRepairTypes()).Returns(repairTypes);

        var result = await _controller.Email(1);
        result.Should().BeOfType<OkResult>();
    }
}

所以问题是Email_ValidRequest_ShouldReturnOk()测试失败,因为Server.Mappath正在返回null,因此未加载模板。正如您所看到的,我尝试初始化当前的HttpContext,但Server.Mappath仍无效。我还尝试使用Server.Mappath替换Path.Combine来电,使用当前的应用域来确定路径。这也不起作用,因为应用程序域指向Debug文件夹。

在对此问题进行了一些研究之后,我意识到不推荐使用Server.MapPath,因为它引入了另一个依赖,这对单元测试来说非常困难。

我对单元测试和整体架构非常陌生,因此非常感谢任何建议。

0 个答案:

没有答案