作为评估,我收到了以下测试用例,因此我可以实现后面的代码:
[TestCase]
public void ProgrammerTest()
{
var address = new Address("56 Main St", "Mesa", "AZ", "38574");
var customer = new Customer("John", "Doe", address);
var company = new Company("Google", address);
Assert.IsNullOrEmpty(customer.Id);
customer.Save();
Assert.IsNotNullOrEmpty(customer.Id);
Assert.IsNullOrEmpty(company.Id);
company.Save();
Assert.IsNotNullOrEmpty(company.Id);
Customer savedCustomer = Customer.Find(customer.Id);
Assert.IsNotNull(savedCustomer);
Assert.AreSame(customer.Address, address);
Assert.AreEqual(savedCustomer.Address, address);
Assert.AreEqual(customer.Id, savedCustomer.Id);
Assert.AreEqual(customer.FirstName, savedCustomer.FirstName);
Assert.AreEqual(customer.LastName, savedCustomer.LastName);
Assert.AreEqual(customer, savedCustomer);
Assert.AreNotSame(customer, savedCustomer);
Company savedCompany = Company.Find(company.Id);
Assert.IsNotNull(savedCompany);
Assert.AreSame(company.Address, address);
Assert.AreEqual(savedCompany.Address, address);
Assert.AreEqual(company.Id, savedCompany.Id);
Assert.AreEqual(company.Name, savedCompany.Name);
Assert.AreEqual(company, savedCompany);
Assert.AreNotSame(company, savedCompany);
customer.Delete();
Assert.IsNullOrEmpty(customer.Id);
Assert.IsNull(Customer.Find(customer.Id));
company.Delete();
Assert.IsNullOrEmpty(company.Id);
Assert.IsNull(Company.Find(company.Id));
}
要求如下:
- 在c#中创建一个类,当子类化时允许这个示例测试代码只使用文件系统存储,不允许预构建数据库;使用文件。
- 创建编译和通过测试用例所需的所有类;你不能修改测试。测试没有错,这不是把戏。
Id
、Save
、Delete
、Find
方法只能在超类中;子类不能自己实现这些方法。
下面是我可以从测试用例中提取的类示例:
public abstract class MyBase
{
public abstract void Save();
public abstract void Delete();
}
public class Company : MyBase
{
public string Id { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
public Company(string name, Address address)
{
this.Name = name;
this.Address = address;
}
internal static Company Find(string id)
{
throw new NotImplementedException();
}
public override void Delete()
{
throw new NotImplementedException();
}
public override void Save()
{
object company = new List<Company>();
if (company != null)
{
// serialize JSON to a string and then write string to a file
File.WriteAllText(@"c:company.json", JsonConvert.SerializeObject(company));
}
}
}
我有为给定代码创建testcase的经验,但不是其他方式,我可以从中提取类,但是,我如何实现方法Save()
,Delete()
,Find(customer.Id)
作为泛型类型而不传递填充的数据类?我知道我可以做像void Save(object obj)
这样的事情,并在基础上实现传递的对象,但测试用例只是调用像customer.Save()
…那么,我该怎么做呢?
提前感谢任何输入!
我认为目的是使用某种序列化来生成对象的副本。
json如果使用json.net,你应该能够使用名称处理来包含序列化消息中的实际对象类型:
JsonSerializerSettings settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
};
string strJson = JsonConvert.SerializeObject(instance, settings);
从如何反序列化JSON到IEnumerable与Newtonsoft JSON。净
protobuf
你也可以使用ProtoInclude的protobuf.net来允许它序列化子类型:
[ProtoContract]
[ProtoInclude(7, typeof(SomeDerivedType))]
class SomeBaseType {...}
[ProtoContract]
class SomeDerivedType {...}
那么基本类型应该能够将this
序列化到内存流并再次反序列化,将副本存储在静态列表中,并让find方法搜索该列表。
受保护的虚拟/抽象成员
另一种方法是将protected virtual
方法添加到子类型中,以完成创建相同对象的所有实际工作。该任务只指定Save
方法需要在基本类型上,而不是需要在没有子类型帮助的情况下完成实际工作。
请注意,由于几个问题,我不会推荐该作业中的实践:
- 通过测试的最简单方法是使用静态可变字段,通常不建议使用这些。 在某些情况下,使用序列化生成深度副本可能是合适的,但我通常不建议这样做。原因是,并不是所有的类型都是可序列化的,而且深层拷贝的构建成本可能会相当低。
- 该指令建议写入文件。单元测试通常应该避免写入磁盘,因为磁盘相对较慢,单元测试需要快速运行才能有用。
- 我发现很少需要副本。在许多情况下,不可变对象更容易使用,不需要复制。
- 总的来说,这个测试似乎相当荒谬。如果我在野外看到它,它会触发很多wtf。