为了确保重构正确。重构之后一定要把所有的CASE在跑一遍,确定所有的都PASS。
  To-Do-List:
  猜测数字
  输入验证
  生成答案
  输入次数
  输出猜测结果
  验证搞定了。我们来整整随机数。
  分析需求:产品代码需要一个随机生成的答案。(1)不重复。(2)4位(3)数字。
  这里有个问题:大家都知道随机数是个概率的问题。因为每次生成的数字都不一样。看看之前Guesser类的代码。
public class Guesser
{
private const string AnswerNumber = "2975";
public string Guess(string inputNumber)
{
var aCount = 0;
var bCount = 0;
for (var index = 0; index < AnswerNumber.Length; index++)
{
if (AnswerNumber[index]==inputNumber[index])
{
aCount++;
continue;
}
if (AnswerNumber.Contains(inputNumber[index].ToString()))
{
bCount++;
}
}
return string.Format("{0}a{1}b", aCount, bCount);
}
}
  这里我们如果把private const string AnswerNumber = "2975";改为随机的话,那Guesser类测试的结果是不能确定的。也是说测试依赖了一些可变的东西。比如:随机数、时间等等。
  遇到这种情况应该怎么办呢?一种随机数是给产品代码用,我们可以MOCK另外一种"固定随机数"(但是要满足生成随机数的条件)来给测试用。
  还是一样先写测试。
[TestClass]
public class AnswerGeneratorTest
{
[TestMethod]
public void should_pass_when_answer_generator_number_is_four_digits_and_fully_digital()
{
Regex regex = new Regex(@"^d{4}$");
var answerGenerator = new AnswerGenerator();
var actual = regex.IsMatch(answerGenerator.Generate());
Assert.AreEqual(true, actual);
}
[TestMethod]
public void should_pass_when_answer_generator_number_do_not_repeat()
{
var answerGenerator = new AnswerGenerator();
var actual = answerGenerator.Generate().Distinct().Count() == 4;
Assert.AreEqual(true, actual);
}
}
   实现AnswerGenerator类让测试通过。
   引用cao大一段代码稍加修改
public class AnswerGenerator
{
public string Generate()
{
var answerNumber = new StringBuilder();
Enumerable.Range(0, 9)
.Select(x => new { v = x, k = Guid.NewGuid().ToString() })
.OrderBy(x => x.k)
.Select(x => x.v)
.Take(4).ToList()
.ForEach(num => answerNumber.Append(num.ToString()));
return answerNumber.ToString();
}
}
  运行测试。

  为了解决测试依赖可变的问题。定义IAnswerGenerator。让两种随机数类继承。
public interface IAnswerGenerator
{
string Generate();
}
[csharp] view plaincopy
public class AnswerGenerator : IAnswerGenerator
{
public string Generate()
{
var answerNumber = new StringBuilder();
Enumerable.Range(0, 9)
.Select(x => new { v = x, k = Guid.NewGuid().ToString() })
.OrderBy(x => x.k)
.Select(x => x.v)
.Take(4).ToList()
.ForEach(num => answerNumber.Append(num.ToString()));
return answerNumber.ToString();
}
}
public class AnswerGeneratorForTest : IAnswerGenerator
{
public string Generate()
{
return "2975";
}
}