0

我刚开始使用 MSpec(James Broome 的 AutoMocking)和 RhinoMocks 使用 BDD/TDD。以下是我的实践项目的摘录:

namespace Tests.VideoStore.Controllers
{
    public abstract class context_for_movie_controller :
    Specification<MovieController>
    {
        private static IList<Movie> movies;
        protected static IMovieRepository _movieRepository;
        protected static ActionResult _result;
        protected static string title;
        protected static string director;

        Establish context = () =>
        {
            _movieRepository = DependencyOf<IMovieRepository>();
        };
    }

    [Subject(typeof(MovieController))]
    public class when_searching_for_movies_with_director :
    context_for_movie_controller
    {
        Establish context = () =>
        {
            title = null;
            director = "James Cameron";

            var movie4 = new Movie {
                Title = "Terminator", Director = "James Cameron"};
            var movie6 = new Movie {
                Title = "Avatar", Director = "James Cameron"};

            movies = new List<Movie> {movie4, movie6};

            // Repository returns all movies.
            _movieRepository.Stub(x => x.FindMovies(title, director))
            .Return(movies);
        };

        Because of = () => _result = subject.Find(title, director);

        It should_fetch_movies_from_the_repository = () =>
            _movieRepository.AssertWasCalled(x =>
                x.FindMovies(title, director));

        It should_return_a_list_of_movies_matching_the_director = () =>
            _result.ShouldBeAView().And()
            .ShouldHaveModelOfType<IEnumerable<Movie>>)
            .And().ShouldContainOnly(movies);
    }

如您所见,我在 MovieRepository 类中删除了 FindMovies() 方法。然后我调用 MoviesController.Find() 操作。我的问题是,是否应该有一个断言来检查控制器是否调用了存根方法(FindMovies)?或者也许我应该只关心返回的结果而不关心它的来源?此外,“should_fetch_movies_from_the_repository”的规范看起来很像一项工程任务,而不是客户可能理解的东西——它在 BDD 中有它的位置吗?

4

1 回答 1

1

断言要遵循的一般规则是断言针对输出交互,而不是输入交互。

FindMovies 存根正在向调用它的类返回一个“电影”集合,然后您正在通过“它应该返回与导演匹配的电影列表”断言验证该类是否收到了正确的列表。如果调用 FindMovies 方法,则此断言将失败。

因此,您不需要针对 FindMovies 方法声明调用。

为了反驳这一点,如果您有一个纯输出的模拟或存根 - 假设由 Presenter 类调用 IView 接口,那么您确实想要断言反对被调用的 IView。例如,这段代码:


public class MyPresenter
{
  ... other code here

  public DoSomething()
  {
    IList data = GetSomeData();
    myView.DisplayData(data);

  }
}

你会想要断言 view.DisplayData 方法在这种情况下被调用,因为你没有从这个调用中检索任何可以被另一个测试断言的东西。

至于“从存储库中获取”-您的客户当然会关心这一点。他们希望系统将电影保存到存储中并从存储中加载它们。然而...... FindMovies 调用是被测试类的输入,因此根本没有必要拥有这个资产或测试。如果未调用 FindMovies 方法,则其他测试将失败并让您知道有问题。

于 2010-02-25T14:48:21.437 回答