应用程序 MVC Moq 中的最小起订量 File.Delete (IFileSystem)

How moq File.Delete (IFileSystem) in app MVC Moq

我的方法有效

[HttpPost]
    public async Task<ActionResult> DeleteTeam(int id)
    {
        Team team = await teamRepository.DeleteTeamAsync(id);
        var fileToDeletePath = Path.Combine(Server.MapPath("~/Images/NBAlogoImg/"), team.Path);

        if (System.IO.File.Exists(fileToDeletePath))
        {
            System.IO.File.Delete(fileToDeletePath);
        }
        if (team != null)
        {
            TempData["message"] = string.Format("{0} был удален", team.Name);
        }
        return RedirectToAction("Index", "Player");
    }

我尝试做一个测试,但是没有成功

 [TestMethod]
    public async Task CanDeletePlayerAsync()
    {
        //Arrange
        Mock<ITeamRepository> teamsMock = new Mock<ITeamRepository>();

        Team team2 = new Team { Id = 2, Name = "Boston" , Path = "CHi.png" };
        Team team3 = new Team { Id = 3, Name = "Lakers" };

        string fullPath = ("~/Images/NBAlogoImg/");

        var serverMock = new Mock<HttpServerUtilityBase>();
        serverMock.Setup(x => x.MapPath(fullPath)).Returns(@"s:\work");

        var httpContextMock = new Mock<HttpContextBase>();
        httpContextMock.Setup(x => x.Server).Returns(serverMock.Object);

        var mockFile = new Mock<IFileSystem>();

        TeamController controller = new TeamController(teamsMock.Object);
        controller.ControllerContext = new ControllerContext(httpContextMock.Object, new RouteData(), controller);

        teamsMock.Setup(m => m.DeleteTeamAsync(team2.Id)).Returns(Task.FromResult(team2));

        // Act
        ActionResult result = await controller.DeleteTeam(team2.Id);
        mockFile.Verify(x => x.File.Delete(@"s:\work\file.png"));

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

如果我删除团队,我添加了从应用程序中删除图像的功能。完美无缺,但是如何通过最小起订量进行测试我尝试了一些未成功。

我有错误信息

Expected invocation on the mock at least once, but was never performed: x => x.File.Delete("s:\work\file.png") No setups configured. No invocations performed.

怎么解决的?我已经下载 IFileSystem 并制作了最小起订量,但验证无效。

一个明显的解决方案是将您的 File.Delete 调用包装在自定义 Class 中,它实现了一个自定义接口,例如,

public interface IFileOperations
{
    void Delete(string path);
}

对于您的系统操作,您可以创建一个包装器 class。

public class SystemFileOperations:IFileOperations
{
    public void Delete(string path)
    {
        File.Delete(path);
    }
}

现在您可以更改原始代码以确保在所有需要的地方注入 SystemFileOperations IFileOperations.Delete。

private IFileOperations _fileOperations;
public ControllerName(IFileOperations operations)
{
_fileOperations = operations;
}

随后将替换下一行

System.IO.File.Delete(fileToDeletePath);

 _fileOperations.Delete(fileToDeletePath);

对于模拟,你可以

var mock = new Mock<IFileOperations>();
mock.Verify(x=>x.Delete(path),Times.AtLeastOnce());

请注意,在您的情况下,由于 File.Exists 的使用,如果您愿意,您可能还必须模拟它并遵循相同的模式