在AutoCAD中运行自动化测试得到eLockViolation
**** Hidden Message ***** 我猜你的测试方法测试的是你在自定义命令中使用的CAD DLL方法(CommandMethod[]),而不是CommandMethod本身。当AutoCAD。NET API代码修改绘图数据库中的任何东西,数据库的文件必须被锁定。当从CommandMethod执行代码时,CommandMethod在文档上下文中执行时会自动锁定文档(除非CommandMethod有其CommandFlags。会话标志设置,例如代码在应用程序上下文中执行)。所以,对于你的每一个测试方法,如果CAD。要测试的. NET代码是要对当前绘图的数据库进行修改,你需要先锁定文件。类似于:
void testsomethemodincaddll()
{
var DWG As Application。document manager . MdiActiveDocument;
使用(dwg。LockDocument())
{
//您的测试代码在这里
}
}
当然,如果CAD。NET代码不会更改打开的图形中的任何内容,因此无需锁定它。
如果没有任何代码查看,很难判断出哪里出了问题。我没有在整个过程中使用CAD测试,但iirc它在AutoCAD过程中通过命令运行控制台和nunit。如果诺曼的回答不起作用,请发布一些代码或链接到回购协议,以便我们查看。 感谢您的回复。我将尝试在此处解释代码。
public void SetUp()
{
zones = new ShimZones(new List());
IZone zone = new Zone("1", "306406", "H");
zones.addZone(zone);
}
ShimZones是一个从普通Zones类继承的对象,它只是重写了一个序列化方法,这是我第一次遇到这个问题。这就是我的工作。
Zones 对象几乎只是一个包含 Zone 对象列表的类,具有一些用于操作该列表的帮助器方法。
[代码 1]
这是为要添加的区域项而调用的构造函数。
在我的非测试代码中,在将新区域添加到Zones对象后,我运行此方法
public void UpdateColor()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = db.TransactionManager;
using (DocumentLock doclock = doc.LockDocument())
using (Transaction tr = tm.StartTransaction())
{
ObjectId newObjectId = this.GetObjectId();
Polyline btr = (Polyline)tr.GetObject(newObjectId, OpenMode.ForWrite);
btr.Color = Autodesk.AutoCAD.Colors.Color.FromColorIndex(ColorMethod.ByAci, (short)color);
tr.Commit();
}
}
但是这似乎是发生崩溃和错误的地方。但是当我运行这个测试方法
public void zone_renumber_to_2()
{
zones.RenumberZone(0, "2", "H");
Assert.IsTrue(zones.zoneList.zoneNum == "2");
Assert.IsTrue(zones.zoneList.color == 116);
}
public void RenumberZone(int index, string newNum, string newThermo)
{
zoneList.zoneNum = newNum;
zoneList.thermostat = newThermo.ToUpper();
zoneList.color = Zone.getZoneColor(this, newNum);
zoneList.UpdateColor();
SerializeZones();
}
时,UpdateColor()方法运行没有问题,并且表示Zone的pline的颜色发生了变化?
非常奇怪的行为,一种方法能够毫无问题地运行 UpdateColor() 方法,而另一种方法则无法运行。
我刚才确实尝试过,将我共享的设置方法包装在using语句中并锁定文档,但结果是一样的。此外,进行颜色更新的方法已经有一个锁定文档的using语句。 这确实有点奇怪
在我看来,唯一有点可疑的是在UpdateColor方法中:要更改的实体由“this.GetObjectId()”标识,这反过来又会追溯到区域对象的句柄。当在测试中调用UpdateColor()时,句柄是否可能属于另一个打开的图形,而不是当前的MdiActiveDocument
我不喜欢在每个CAD操作方法中获取MdiActiveDocument并锁定文档,如果类已经有了识别其依赖关系数据库的方法。在您的情况下,方法是这样的。GetObjectId()已经暗示Zone类本身知道句柄属于哪个数据库。因此,为什么需要获取MdiActiveDocument才能访问数据库,然后访问TransactionManager?您可以这样做:
var newObjectId=this。GetObjectId()
使用(var-tran=newObjectId.Database.TransactionManager.StartTransaction())
{
…
}
这样,您可以将文档锁完全保留在UpdateColor方法之外,并让调用进程决定是否需要锁。例如,在文档上下文中,不需要锁定,而在应用程序上下文(如此处的测试)中,需要在测试调用中显式锁定文档
此外,我们都知道,如果测试涉及AutoCAD过程,则测试实际上会从“单元测试”变为“集成测试”。并且这是困难和耗时的。因此,在很多情况下,我从来都不喜欢这样做,因为这样做不值得花时间。但对于你的区域类。如果需要“单元测试”(我知道,有些老板/公司要求),我会坚持“单元测试”,而不是“集成测试”,也就是说,我会考虑通过为Zone类的单元测试提供一个mocking/empty UpdateColor()方法来取代AutoCAD:毕竟,Zone类单元测试是为了确保在调用RenumberZone()时,应该按照预期发生一些事情,因此,只要调用mocking UpdateColor,单元测试就应该通过。
谢谢你的帮助n.yuan,这是非常有价值的。
我按照您的描述对 UpdateColor 进行了更改
public void UpdateColor()
{
ObjectId newObjectId = this.GetObjectId();
using (Transaction tr = newObjectId.Database.TransactionManager.StartTransaction())
{
Polyline btr = (Polyline)tr.GetObject(newObjectId, OpenMode.ForWrite);
btr.Color = Autodesk.AutoCAD.Colors.Color.FromColorIndex(ColorMethod.ByAci, (short)color);
tr.Commit();
}
}
并对 GetObjectId 进行了一些更改,现在它看起来像这样
public ObjectId GetObjectId()
{
Document doc = Active.Document;
ObjectId newObjectId = new ObjectId();
using (doc.Database.TransactionManager.StartTransaction())
{
long l = Int64.Parse(handle, System.Globalization.NumberStyles.AllowHexSpecifier);
Handle h = new Handle(l);
newObjectId = Active.Database.GetObjectId(false, h, 0);
}
return newObjectId;
}
现在在测试的 Setup 函数中,如果我锁定文档
public void SetUp()
{
using (Active.Document.LockDocument())
{
zones = new ShimZones(new List());
IZone zone = new Zone("1", "306406", "H");
zones.addZone(zone);
}
}
则不会崩溃
,但是在以后的测试中,即使我锁定了文档,也会发生相同的崩溃?
public void zone_renumber_to_2()
{
using (Active.Document.LockDocument())
{
zones.RenumberZone(0, "2", "H");
Assert.IsTrue(zones.zoneList.zoneNum == "2");
Assert.IsTrue(zones.zoneList.color == 116);
}
}
我应该如何存储该句柄的句柄和数据库信息?我正在继承此代码并尝试改进它,同时学习如何为AutoCAD插件编写代码。
再次感谢! 在GetObjectId()方法中引发异常?哪条线
需要注意的一点是:无需使用该方法启动事务
谢谢n元!移除GetObjectId()中的那个事务就修复了它!我想我认为创建一个新的ObjectId对象将保证一个事务。 很高兴听到由于我的“不太确定”提示,问题得到了解决。这仍然是一个令人惊讶和困惑的问题:为什么一个无用的事务,或者一个在DocumentLock范围内打开的事务仍然会引发eLockViolation,而另一个事务在它没有引起异常后立即打开?真奇怪!
页:
[1]