0

我在很多地方读到过,在 TDD 期间使用反射设置内部字段是不好的,因为这可能意味着我们还没有对被测类的接口进行排序。但是,我想提出一个我认为完全合理的场景,除了反射之外,我想不出任何干净的解决方案来解决手头的问题。

这是一个带有相应测试的示例类:

public Class Movie
{
   public string MovieName{get; private set}

   public void AddExternalReview(IMovieReview review)
  {
      //Logic that needs Unit testing.
      if ( review.MovieName.Equals(MovieName) )
      {
         //Do stuff..
      }
  } 
}

单元测试:

[Test]
public Class MovieTests
{
   public void CanAddExternalReview()
   {
      MovieReviewStub movieReviewStub = new MovieReviewStub(); 
      movieReviewStub.MovieName = "The Godfather";

      Movie m = new Movie();
      //Need to Set object m state(i.e set Property MovieName to "The Godfather")
      //Only way to do that seems to be relection.

      m.AddExternalReview(movieReviewStub);
      //Assert on some condition.
   }
}

具有无法由类的“普通”客户端设置的属性是很常见的。但是,UnitTest 类可能需要访问此类属性/字段,以便它可以设置测试所需的相关状态。据我所知,反思是唯一的出路。这一定是一个相当普遍的要求,但网络上的大多数文章/讨论似乎都不赞成在 TDD 中使用反射。任何想法/见解都将受到欢迎。

4

2 回答 2

1

听起来正在测试的逻辑具有未实现的依赖关系。测试有一个未满足的先决条件,而该先决条件是设置值的原因。

代码中没有干净的方法可以在不使用反射的情况下手动设置值。那么为什么要测试代码中逻辑上不会发生的事情呢?(除非代码也使用反射来设置值。在这种情况下,类肯定存在抽象问题。)

如果该类出于某种原因保护该 setter,请在该保护范围内工作。否则,正如您所说,界面没有正确排序。任何逻辑过程设置该值都是测试的先决条件。

于 2012-05-05T00:51:05.963 回答
0

The sentence that puzzles me in your problem description is "It is quite common to have properties that cannot be set by a Class's "normal" Clients." This sounds like you have two (or more) types of clients for your class. If that's the case your different types of clients should see different interfaces. The implementation class however is the same and should not hide the property's setter; writing the test is simple then.

I guess it all boils down to a question of design priorities. When doing TDD I usually favor testability over data hiding and encapsulation. To prioritize the other way round will sometimes make testing hard and non-intuitive - as in your example.

于 2012-05-05T20:21:05.593 回答