返回正确的对象

时间:2014-10-12 17:05:24

标签: c#

我试图完成编程练习但是一次测试失败了。我做错了什么?

任务是:

  

编写管理机器人出厂设置的程序。

     

当机器人从工厂车间出来时,他们没有名字。

     

第一次启动它们时,会生成一个随机名称,例如   RX837或BC811。

     

每隔一段时间我们就需要将机器人重置为工厂   设置,这意味着他们的名字被擦除。下次你   问,它有一个新名字。

该程序的测试如下所示,失败的测试是 Different_robots_have_different_names

public class RobotNameTest
{
    private Robot robot;

    [SetUp]
    public void Setup()
    {
        robot = new Robot();
    }

    [Test]
    public void Robot_has_a_name()
    {
        StringAssert.IsMatch(@"[A-Z]{2}\d{3}", robot.Name);
    }

    [Test]
    public void Name_is_the_same_each_time()
    {
        Assert.That(robot.Name, Is.EqualTo(robot.Name));
    }

    [Test]
    public void Different_robots_have_different_names()
    {
        var robot2 = new Robot();
        Assert.That(robot.Name, Is.Not.EqualTo(robot2.Name));
    }

    [Test]
    public void Can_reset_the_name()
    {
        var originalName = robot.Name;
        robot.Reset();
        Assert.That(robot.Name, Is.Not.EqualTo(originalName));
    }
}

我的代码如下所示:

public class Robot
{
    private List<string> Names = new List<string>();

    private string name { get; set; }
    public string Name { get { return this.name; } }

    public Robot()
    {
        CreateName();
    }

    private void CreateName()
    {
        var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        var random = new Random();
        StringBuilder sb = new StringBuilder();

        sb.Append(
            new string(
                Enumerable.Repeat(chars, 3)
                    .Select(x => x[random.Next(x.Length)]).ToArray()
            )
        );
        sb.Append(random.Next(100, 999));
        if(Names.Any(word => word.Equals(sb.ToString())))
        {
            CreateName();
        }
        else
        {
            name = sb.ToString();
            Names.Add(sb.ToString());
        }
    }

    public void Reset()
    {
        this.name = "";
    }
}

2 个答案:

答案 0 :(得分:3)

使Names静态传递所有测试:

private static List<string> Names = new List<string>();

Static关键字表示正在级别创建成员,而不是对象。

在您的情况下所有机器人将共享指向单个名称列表的链接。删除static关键字将导致Names列表创建 Robot对象。如果你想跟踪Robots构造函数的调用次数,你应该有一个共享的名字列表,它在所有Robot对象中共享。

您的测试失败,因为当创建第二个对象时,它有一个 new 空名称列表,第一个Robot类对此一无所知。因此,在您的情况下,Names.Any(...)将始终返回false。

要阅读更多详细信息,请考虑上面的msdn链接。

答案 1 :(得分:2)

错误并不明显。使用从当前系统时间创建的随机种子初始化Random类。与CPU时钟频率相比,产生系统时间的手表速度缓慢。因此,如果random被调用为快两次,new Random()很可能会使用相同的种子初始化两次。

解决方案:将随机声明为静态并仅初始化一次。

public class Robot
{
    private static Random random = new Random();

    ...
}

现在random只会创建一次,无论您创建多少个机器人。