問題描述
我的典型場(chǎng)景:
- 我處理的遺留代碼有一個(gè)只有生產(chǎn)中的客戶端才有的錯(cuò)誤
- 我附加了一個(gè)調(diào)試器,并找出如何在 他們的 系統(tǒng)上重現(xiàn)該問題給 他們的 輸入.但是,我還不知道為什么會(huì)發(fā)生錯(cuò)誤.
- 現(xiàn)在我想在我的本地系統(tǒng)上編寫一個(gè)自動(dòng)化測(cè)試來嘗試重現(xiàn)然后修復(fù)錯(cuò)誤
- The legacy code I work on has a bug that only a client in production is having
- I attach a debugger and figure out how to reproduce the issue on their system given their input. But, I don't know why the error is happening yet.
- Now I want to write an automated test on my local system to try and reproduce then fix the bug
最后一步真的很難.輸入可能非常復(fù)雜,并且包含大量數(shù)據(jù).手動(dòng)創(chuàng)建輸入(例如:P p = new P(); p.setX("x"); p.setY("x");
想象這樣做 1000 次來創(chuàng)建對(duì)象) 非常繁瑣且容易出錯(cuò).事實(shí)上,您可能會(huì)注意到我剛才給出的示例中有一個(gè)錯(cuò)字.
That last step is really hard. The input can be very complex and have a lot of data to it. Creating the input by hand (eg: P p = new P(); p.setX("x"); p.setY("x");
imagine doing this 1000 times to create the object) is very tedious and error prone. In fact you may notice there's a typo in the example I just gave.
是否有一種自動(dòng)化的方法可以從我的調(diào)試器中的斷點(diǎn)獲取字段并生成將創(chuàng)建該對(duì)象的源代碼,并以相同的方式填充?
我想出的唯一方法就是序列化這個(gè)輸入(例如,使用 Xstream).我可以將其保存到文件中并在自動(dòng)化測(cè)試中將其讀回.這有一個(gè)主要問題:如果類以某些方式更改(例如:重命名字段/getter/setter 名稱),我將無法再反序列化對(duì)象.換句話說,測(cè)試非常脆弱.
The only thing I've come up with is to serialize this input (using Xstream, for example). I can save that to a file and read it back in in an automated test. This has a major problem: If the class changes in certain ways (eg: a field/getter/setter name is renamed), I won't be able to deserialize the object anymore. In other words, the tests are extremely fragile.
推薦答案
眾所周知,Java 標(biāo)準(zhǔn)序列化在對(duì)象更改其版本(內(nèi)容、字段命名)時(shí)不是很有用.它適用于快速演示項(xiàng)目.
Java standard serialisation is well know to be not very usefull when objects change their version ( content, naming of fields). Its fine for quick demo projects.
更適合您的需求,是 objetcs 支持您自己的(二進(jìn)制)自定義序列化的方法:
這并不難,使用 DataOutputStream
寫出一個(gè)對(duì)象的所有字段.但是現(xiàn)在引入versiong,首先寫出一個(gè)versionId
.只有一個(gè)版本的對(duì)象,寫出 versionId 1.這樣以后,當(dāng)您必須在對(duì)象中引入更改時(shí),刪除字段、添加字段、提高版本號(hào).
More suitable for your needs, is the approach that objetcs support your own (binary) custom serialisation:
This is not difficult, use DataOutputStream
to write out all fields of an object. But now introduce versiong, by first writing out a versionId
. Objects that have only one version, write out versionId 1. That way you can later, when you have to introduce a change in your objetcs, remove fields, add fields, raise the version number.
這樣的 ICustomSerializable
將首先在 readObject() 方法中從輸入流中讀取版本號(hào),并根據(jù)版本 ID 調(diào)用 readVersionV1() 或例如 readVersionV2().
Such a ICustomSerializable
will then first read out the version number from the input stream, in a readObject() method, and depending on the version Id call readVersionV1() or e.g readVersionV2().
public Interface ICustomSerializable {
void writeObject(DataOutputStream dos);
Object readObject(DataInputStream dis);
}
public Class Foo {
public static final VERSION_V1 = 1;
public static final VERSION_V2 = 2;
public static final CURRENT_VERSION = VERSION_V2;
private int version;
private int fooNumber;
private double fooDouble;
public void writeObject(DataOutputStream dos) {
dos.writeInt(this.version);
if (version == VERSION_V1) {
writeVersionV1(dos);
} else (version == VERSION_V2) {
writeVersionV2(dos);
} else {
throw new IllegalFormatException("unkown version: " + this.version);
}
}
public void writeVersionV1(DataOutputStream dos) {
writeInt(this.fooNumber);
writeDouble(this.fooValue);
}
}
需要更多的 getter 和 setter,以及將版本初始化為 CURRENT_VERSION 的構(gòu)造函數(shù).
Further getter and setter, and a constructor with initialised the version to CURRENT_VERSION is needed.
如果您更改或添加適當(dāng)?shù)淖x寫版本,這種序列化是安全的重構(gòu).對(duì)于使用不受您控制的外部庫中的類的復(fù)雜對(duì)象,它可以做更多的工作,但字符串、列表很容易序列化.
This kind of serialisazion is safe to refactoring if you change or add also the appropriate read and write version. For complex objects using classes from external libs not und your controll, it can be more work, but strings, lists are easily serialized.
這篇關(guān)于如何生成源代碼來創(chuàng)建我正在調(diào)試的對(duì)象?的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!