乐筑天下

搜索
欢迎各位开发者和用户入驻本平台 尊重版权,从我做起,拒绝盗版,拒绝倒卖 签到、发布资源、邀请好友注册,可以获得银币 请注意保管好自己的密码,避免账户资金被盗
查看: 188|回复: 9

在AutoCAD中运行自动化测试得到eLockViolation

[复制链接]

3

主题

10

帖子

1

银币

初来乍到

Rank: 1

铜币
22
发表于 2021-10-8 12:40:05 | 显示全部楼层 |阅读模式

本帖以下内容被隐藏保护;需要你回复后,才能看到!

游客,如果您要查看本帖隐藏内容请回复
回复

使用道具 举报

4

主题

219

帖子

4

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
238
发表于 2021-10-10 10:38:43 | 显示全部楼层
我猜你的测试方法测试的是你在自定义命令中使用的CAD DLL方法(CommandMethod[]),而不是CommandMethod本身。当AutoCAD。NET API代码修改绘图数据库中的任何东西,数据库的文件必须被锁定。当从CommandMethod执行代码时,CommandMethod在文档上下文中执行时会自动锁定文档(除非CommandMethod有其CommandFlags。会话标志设置,例如代码在应用程序上下文中执行)。
所以,对于你的每一个测试方法,如果CAD。要测试的. NET代码是要对当前绘图的数据库进行修改,你需要先锁定文件。类似于:
[Test]
void testsomethemodincaddll()
{
var DWG As Application。document manager . MdiActiveDocument;
使用(dwg。LockDocument())
{
//您的测试代码在这里
}
}
当然,如果CAD。NET代码不会更改打开的图形中的任何内容,因此无需锁定它。
回复

使用道具 举报

23

主题

239

帖子

6

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
327
发表于 2021-10-11 06:39:34 | 显示全部楼层
如果没有任何代码查看,很难判断出哪里出了问题。我没有在整个过程中使用CAD测试,但iirc它在AutoCAD过程中通过命令运行控制台和nunit。如果诺曼的回答不起作用,请发布一些代码或链接到回购协议,以便我们查看。
回复

使用道具 举报

3

主题

10

帖子

1

银币

初来乍到

Rank: 1

铜币
22
发表于 2021-10-11 11:14:48 | 显示全部楼层
感谢您的回复。我将尝试在此处解释代码。
  1. [SetUp]
  2.         public void SetUp()
  3.         {
  4.             zones = new ShimZones(new List[I]());
  5.             IZone zone = new Zone("1", "306406", "H");
  6.             zones.addZone(zone);
  7.             
  8.         }

ShimZones是一个从普通Zones类继承的对象,它只是重写了一个序列化方法,这是我第一次遇到这个问题。这就是我的工作。
Zones 对象几乎只是一个包含 Zone 对象列表的类,具有一些用于操作该列表的帮助器方法。
[代码 1]
这是为要添加的区域项而调用的构造函数。
在我的非测试代码中,在将新区域添加到Zones对象后,我运行此方法
  1. public void UpdateColor()
  2.         {
  3.             Document doc = Application.DocumentManager.MdiActiveDocument;
  4.             Editor ed = doc.Editor;
  5.             Database db = doc.Database;
  6.             Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = db.TransactionManager;
  7.             using (DocumentLock doclock = doc.LockDocument())
  8.             using (Transaction tr = tm.StartTransaction())
  9.             {
  10.                 ObjectId newObjectId = this.GetObjectId();
  11.                 Polyline btr = (Polyline)tr.GetObject(newObjectId, OpenMode.ForWrite);
  12.                 btr.Color = Autodesk.AutoCAD.Colors.Color.FromColorIndex(ColorMethod.ByAci, (short)color);
  13.                 tr.Commit();
  14.             }
  15.         }

但是这似乎是发生崩溃和错误的地方。但是当我运行这个测试方法
  1. [Test]
  2.         [Description("Does renumbering the zone work?")]
  3.         public void zone_renumber_to_2()
  4.         {
  5.             zones.RenumberZone(0, "2", "H");
  6.             Assert.IsTrue(zones.zoneList[0].zoneNum == "2");
  7.             Assert.IsTrue(zones.zoneList[0].color == 116);
  8.         }
  1. public void RenumberZone(int index, string newNum, string newThermo)
  2.         {
  3.             zoneList[index].zoneNum = newNum;
  4.             zoneList[index].thermostat = newThermo.ToUpper();
  5.             zoneList[index].color = Zone.getZoneColor(this, newNum);
  6.             zoneList[index].UpdateColor();
  7.             SerializeZones();
  8.         }

时,UpdateColor()方法运行没有问题,并且表示Zone的pline的颜色发生了变化?
非常奇怪的行为,一种方法能够毫无问题地运行 UpdateColor() 方法,而另一种方法则无法运行。
回复

使用道具 举报

3

主题

10

帖子

1

银币

初来乍到

Rank: 1

铜币
22
发表于 2021-10-11 16:10:50 | 显示全部楼层

我刚才确实尝试过,将我共享的设置方法包装在using语句中并锁定文档,但结果是一样的。此外,进行颜色更新的方法已经有一个锁定文档的using语句。
回复

使用道具 举报

4

主题

219

帖子

4

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
238
发表于 2021-10-12 10:25:01 | 显示全部楼层
这确实有点奇怪
在我看来,唯一有点可疑的是在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,单元测试就应该通过。
回复

使用道具 举报

3

主题

10

帖子

1

银币

初来乍到

Rank: 1

铜币
22
发表于 2021-10-12 15:52:45 | 显示全部楼层
谢谢你的帮助n.yuan,这是非常有价值的。
我按照您的描述对 UpdateColor 进行了更改
  1. public void UpdateColor()
  2.         {
  3.             ObjectId newObjectId = this.GetObjectId();
  4.             
  5.             using (Transaction tr = newObjectId.Database.TransactionManager.StartTransaction())
  6.             {
  7.                
  8.                 Polyline btr = (Polyline)tr.GetObject(newObjectId, OpenMode.ForWrite);
  9.                 btr.Color = Autodesk.AutoCAD.Colors.Color.FromColorIndex(ColorMethod.ByAci, (short)color);
  10.                 tr.Commit();
  11.             }
  12.         }

并对 GetObjectId 进行了一些更改,现在它看起来像这样
  1. public ObjectId GetObjectId()
  2.         {
  3.             Document doc = Active.Document;
  4.             ObjectId newObjectId = new ObjectId();
  5.             
  6.             using (doc.Database.TransactionManager.StartTransaction())
  7.             {
  8.                 long l = Int64.Parse(handle, System.Globalization.NumberStyles.AllowHexSpecifier);
  9.                 Handle h = new Handle(l);
  10.                 newObjectId = Active.Database.GetObjectId(false, h, 0);
  11.             }
  12.             return newObjectId;
  13.         }

现在在测试的 Setup 函数中,如果我锁定文档
  1. [SetUp]
  2.         public void SetUp()
  3.         {
  4.             using (Active.Document.LockDocument())
  5.             {
  6.                 zones = new ShimZones(new List[I]());
  7.                 IZone zone = new Zone("1", "306406", "H");
  8.                 zones.addZone(zone);
  9.             }
  10.                
  11.         }

则不会崩溃
,但是在以后的测试中,即使我锁定了文档,也会发生相同的崩溃?
  1. [Test]
  2.         [Description("Does renumbering the zone work?")]
  3.         public void zone_renumber_to_2()
  4.         {
  5.             using (Active.Document.LockDocument())
  6.             {
  7.                 zones.RenumberZone(0, "2", "H");
  8.                 Assert.IsTrue(zones.zoneList[0].zoneNum == "2");
  9.                 Assert.IsTrue(zones.zoneList[0].color == 116);
  10.             }
  11.             
  12.         }

我应该如何存储该句柄的句柄和数据库信息?我正在继承此代码并尝试改进它,同时学习如何为AutoCAD插件编写代码。
再次感谢!
回复

使用道具 举报

4

主题

219

帖子

4

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
238
发表于 2021-10-13 09:05:20 | 显示全部楼层
在GetObjectId()方法中引发异常?哪条线
需要注意的一点是:无需使用该方法启动事务
回复

使用道具 举报

3

主题

10

帖子

1

银币

初来乍到

Rank: 1

铜币
22
发表于 2021-10-13 10:31:32 | 显示全部楼层
谢谢n元!移除GetObjectId()中的那个事务就修复了它!我想我认为创建一个新的ObjectId对象将保证一个事务。
回复

使用道具 举报

4

主题

219

帖子

4

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
238
发表于 2021-10-14 08:50:03 | 显示全部楼层
很高兴听到由于我的“不太确定”提示,问题得到了解决。这仍然是一个令人惊讶和困惑的问题:为什么一个无用的事务,或者一个在DocumentLock范围内打开的事务仍然会引发eLockViolation,而另一个事务在它没有引起异常后立即打开?真奇怪!
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

  • 微信公众平台

  • 扫描访问手机版

  • 点击图片下载手机App

QQ|关于我们|小黑屋|乐筑天下 繁体中文

GMT+8, 2025-2-4 01:05 , Processed in 0.216608 second(s), 72 queries .

© 2020-2025 乐筑天下

联系客服 关注微信 帮助中心 下载APP 返回顶部 返回列表