Ser*_*gey 2 c# asp.net asp.net-mvc unit-testing asp.net-mvc-2
我试着测试我的控制器
[TestMethod]
public void Index()
{
AdminController controller = new AdminController();
ViewResult result = controller.Index() as ViewResult;
Assert.IsNotNull(result);
}
Run Code Online (Sandbox Code Playgroud)
这是Index()代码:
public ActionResult Index()
{
var repository = new PostsRepository();
var posts = repository.GetAllPosts();
return View(posts);
}
Run Code Online (Sandbox Code Playgroud)
库:
public class PostsRepository : IPostsRepository
{
PostsDataContext _dataContext = new PostsDataContext();
public IQueryable<Post> GetAllPosts()
{
var posts = from t in _dataContext.Posts select t;
return posts;
}
public Post GetPostById(int id)
{
var post = from t in _dataContext.Posts
where t.id == id
select t;
return post.First();
}
}
Run Code Online (Sandbox Code Playgroud)
但我的Index()单元测试失败并出现错误:
Test method MvcBlog.Tests.Controllers.AdminControllerTest.Index threw exception:
System.NullReferenceException: Object reference not set to an instance of an object.
Run Code Online (Sandbox Code Playgroud)
堆栈跟踪:
MvcBlog.Models.PostsDataContext..ctor() in C:\Users\cL1Nk3r\Documents\Visual Studio 2010\Projects\MvcBlog\MvcBlog\Models\Posts.designer.cs: line 38
MvcBlog.Repository.PostsRepository..ctor() in C:\Users\cL1Nk3r\Documents\Visual Studio 2010\Projects\MvcBlog\MvcBlog\Repository\PostsRepository.cs: line 11
MvcBlog.Controllers.AdminController.Index() in C:\Users\cL1Nk3r\Documents\Visual Studio 2010\Projects\MvcBlog\MvcBlog\Controllers\AdminController.cs: line 19
MvcBlog.Tests.Controllers.AdminControllerTest.Index() in C:\Users\cL1Nk3r\Documents\Visual Studio 2010\Projects\MvcBlog\MvcBlog.Tests\Controllers\AdminControllerTest.cs: line 19
Run Code Online (Sandbox Code Playgroud)
为什么这是一个错误?
如果我只是运行我的应用程序,它可以正常工作.
源代码下载:http://dl.dropbox.com/u/14053604/MvcBlog.rar
问题是控制器操作中的以下行:
var repository = new PostsRepository();
Run Code Online (Sandbox Code Playgroud)
在这里,您将控制器绑定到存储库的特定实现,这使得单独进行单元测试非常困难.为了实现控制器和数据访问层之间的耦合较弱,我建议您使用构造函数注入:
public class PostsController: Controller
{
private readonly IPostsRepository _repository;
public PostsController(IPostsRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
var posts = _repository.GetAllPosts();
return View(posts);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您的控制器完全与可能依赖于数据库等的存储库的特定实现分离.现在您可以使用模拟框架(如Rhino Mocks或Moq)为单元测试提供此存储库的虚拟实现.
就个人而言,我非常喜欢MVCContrib TestHelper,它可以与Rhino Mocks配合使用,并且可以对控制器动作进行非常优雅的单元测试.因此,一旦您将控制器与存储库的特定实现分离,如我所示,您可以进行以下单元测试:
[TestMethod]
public void PostsController_Index_Action_Should_Fetch_All_Posts_From_Repository()
{
// arrange
var postsRepositoryStub = MockRepository.GenerateStub<IPostsRepository>();
var sut = new PostsController(postsRepositoryStub);
var expectedPosts = new Post[0];
postsRepositoryStub.Stub(x => x.GetAllPosts).Return(expectedPosts);
// act
var actual = sut.Index();
// assert
actual
.AssertViewRendered()
.WithViewData<IEnumerable<Post>>()
.ShouldBe(expectedPosts);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1966 次 |
| 最近记录: |