如何在基类中实现通用的Save()函数



作为评估,我收到了以下测试用例,因此我可以实现后面的代码:

[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#中创建一个类,当子类化时允许这个示例测试代码只使用文件系统存储,不允许预构建数据库;使用文件。
  • 创建编译和通过测试用例所需的所有类;你不能修改测试。测试没有错,这不是把戏。
  • IdSaveDeleteFind方法只能在超类中;子类不能自己实现这些方法。

下面是我可以从测试用例中提取的类示例:

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。

相关内容

  • 没有找到相关文章

最新更新