让我们假设我为我的示例博客应用程序创建了以下测试:
[TestClass]
public class when_the_blog_controller_index_action_executes : BlogControllerTests
{
//...
[TestMethod]
[TestCategory("BlogController")]
public void it_should_pass_the_latest_blogentries_to_the_view()
{
blogs = new List<BlogEntry>() { new BlogEntry("title1", "b1"), new BlogEntry("title2", "b2"), new BlogEntry("title3", "b3") };
blogServiceMock = new Mock<IBlogService>();
blogServiceMock.Setup(s => s.GetLatestBlogEntries())
.Returns(blogs);
var controller = new BlogController(blogServiceMock.Object);
var model = ((ViewResult)controller.Index()).Model as IEnumerable<BlogEntry>;
Assert.IsTrue(blogs.SequenceEqual(model));
blogServiceMock.VerifyAll();
}
}
在BlogController实现之后,我有一个正在运行的测试:
public class BlogController : Controller
{
IBlogService blogService;
public BlogController(IBlogService blogService)
{
this.blogService = blogService;
}
public ActionResult Index()
{
var model = blogService.GetLatestBlogEntries();
return View(model);
}
}
那么下一步是什么?我应该为IBlogService创建实现(带有测试),还是在创建存储库(带有测试)之后? 如果我有这样的服务,基本上我不会测试任何东西,因为我只是嘲笑存储库......
public class BlogService : IBlogService
{
IBlogRepository blogRepository;
public BlogService(IBlogRepository blogRepository)
{
this.blogRepository = blogRepository;
}
public IEnumerable<BlogEntry> GetLatestBlogEntries()
{
return blogRepository.GetLatestBlogEntries();
}
}
答案 0 :(得分:1)
下一步是对您编写的BlogService实现进行单元测试。在此测试中,您应确保在模拟的存储库上调用正确的方法。如果稍后您的服务逻辑发展并且您有一些方法执行的不仅仅是CRUD存储库访问,那么您的测试将开始变得更有意义。
您当前对此服务的实现只是将调用委托给存储库,这就是您应该进行单元测试的内容。
如果您发现自己的服务层由简单的CRUD方法组成,除了将调用委托给某个存储库之外,您可能应该问自己该服务层的用处以及是否也不可能从控制器直接使用存储库。
答案 1 :(得分:0)
> TDD Process Outside-In?
我会在两个嵌套循环中使用外向内(BDD)和内外(TDD)的混合,如Behavior-Driven Development with SpecFlow and WatiN
中所述* writing a failing (outside-in) integration tests
* writing a failing (inside out) unit test as part of the solution of the integration test
* making the unittest pass
* refactor
* writing the next failing unit test as part of the integration test
* unitl the integration test passes
* writing the next failing integration tests