单元测试MVC控制器

时间:2013-12-07 22:33:30

标签: asp.net-mvc unit-testing mocking

我正在试图找出为MVC应用程序构建单元测试的最佳方法。我创建了一个简单的模型和接口,由控制器构造函数使用,以便测试框架(Nsubstitute)可以传递存储库的模拟版本。正如预期的那样,这个测试通过了。

我的问题是现在我想更进一步,在IHomeRepository的“真实”实例中测试文件I / O操作。此实现应从App_Data目录中的文件读取值。

我已尝试在不传递模拟版本的IHomeRepsotory的情况下构建测试,但是当我运行测试时HttpContext.Current为null。

我需要模拟HttpContext吗?我是否以正确的方式解决这个问题?

//The model
public class VersionModel
{
    public String BuildNumber { get; set; }
}



//Interface defining the repository
public interface IHomeRepository
{
    VersionModel Version { get; }
}


//define the controller so the unit testing framework can pass in a mocked reposiotry.  The default constructor creates a real repository
public class HomeController : Controller
{

    public IHomeRepository HomeRepository;

    public HomeController()
    {
        HomeRepository = new HomeRepoRepository();
    }

    public HomeController(IHomeRepository homeRepository)
    {
        HomeRepository = homeRepository;
    }
.
.
.

}


class HomeRepoRepository : IHomeRepository
{
    private VersionModel _version;

    VersionModel IHomeRepository.Version
    {
        get
        {
            if (_version == null)
            {
                var absoluteFileLocation = HttpContext.Current.Server.MapPath("~/App_Data/repo.txt");
                if (absoluteFileLocation != null)
                {           
                    _version = new VersionModel() //read the values from file (not shown here)
                    {
                        BuildNumber = "value from file",
                    };
                }
                else
                {
                    throw new Exception("path is null");
                }
            }
            return _version;
        }
    }
}



[Fact]
public void Version()
{
    // Arrange
    var repo = Substitute.For<IHomeRepository>();  //using Nsubstitute, but could be any mock framework
    repo.Version.Returns(new VersionModel
    {
       BuildNumber = "1.2.3.4",
    });

    HomeController controller = new HomeController(repo);  //pass in the mocked repository

    // Act
    ViewResult result = controller.Version() as ViewResult;
    var m = (VersionModel)result.Model;

    // Assert
    Assert.True(!string.IsNullOrEmpty(m.Changeset));
}

1 个答案:

答案 0 :(得分:1)

我相信你想测试IHomeRepository的真实实例,它连接到一个真实的数据库。在这种情况下,您需要一个App.config file, which specify the connection string。这不是单元测试,而是集成测试。如果HttpContext为null,您仍然can fake the HttpContext,从数据库中检索实际数据。另请参阅here