单元测试气味

发布于 2024-07-25 21:03:28 字数 575 浏览 4 评论 0原文

我正在尝试更改 ArcGIS 的单元测试,并开始使用模拟(我使用 rhino)。
当我开始编写测试时,我注意到我必须开始模拟很多对象,并存根很多方法,即使是单个测试也无法通过。
例如 - 我的控制器首先获取一个 RelationshipClass (因此我需要存根 IWorkspace 和返回的 IRelationshipClass),然后还获取一个 >IFeature(存根),最后调用 stubRelClass.GetRelatedObjects(stubFeature),返回其他 IFeatureISet

为了让它通过而必须存根这么多对象和方法是正常的吗? 我也感到 就像我真的需要跳过代码(是的 - 我知道我应该先编写测试,我仍在尝试这个),以便弄清楚下一步要存根什么,以及我应该返回什么。

我在模拟实现多个接口的 com 类时也遇到问题。 在生产代码中,我对它们之间的接口进行了 QI 处理。 如何创建一个在运行时实现这两个接口的模拟?

I am trying to change my unit testing of ArcGIS, and start using mocks (I use rhino).
When I started to get into writing the tests, I noticed I have to start mocking a lot of objects, and stub a lot of methods for even a single test to pass.
For example - my controller first gets a RelationshipClass (so I need to stub the IWorkspace and the returned IRelationshipClass), then also gets an IFeature (A stub), and finally calls stubRelClass.GetRelatedObjects(stubFeature), to return an ISet of other IFeatures.

Is it normal to have to stub so many objects and methods just to make it pass? I also feel
like I really need to step over the code (yeah - I know I should have written the tests first, I am still trying this one), in order to figure out what to stub out next, and what I should return.

I am also having problem with mocking com classes which implement more than one interface. In the production code I QI them between the interfaces. How can I create a mock that implements both interfaces at runtime?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

十雾 2024-08-01 21:03:28

是的,有时您必须模拟很多对象,具体取决于您的注入链。 如果您要深入多个级别,则可能表明存在设计错误 - 依赖于 API 下三层的数据的对象可能不是松散耦合的。 您应该能够通过在某个时刻返回某种具有您正在测试的层需要的必要属性的假对象来将链消灭在萌芽状态。

您还应该能够在 [SetUp] 方法中完成大部分模拟,然后让每个测试仅更改一两件事。

为了模拟多个接口,Rhino 有 MultiMock 的概念。 我相信你所追求的语法是:

var mock = 
    MockRepository.DynamicMultiMock<MyType>(
              typeof(Interface1), 
              typeof(Interface2), 
              ....);

Depending on your injection chain, yes, sometimes you have to mock a lot of objects. If you're going multiple levels deep though, it may be indicative of a design fault - objects that are relying on data that is three layers down into your API may not be loosely coupled. You should be able to nip the chain in the bud by just returning a fake object of some kind at some point that has the necessary properties that the layer you're testing at needs.

You should also be able to do most of your mocking in a [SetUp] method and then have each test just change one or two things.

For mocking multiple interfaces, Rhino has the concept of a MultiMock. I believe the syntax you're after is:

var mock = 
    MockRepository.DynamicMultiMock<MyType>(
              typeof(Interface1), 
              typeof(Interface2), 
              ....);
海风掠过北极光 2024-08-01 21:03:28

这可能是高耦合的标志 - 这反过来又意味着需要减少依赖性(这将提高设计和可测试性)。 作为粗略准则,一个对象最多应有 4-6 个协作者。 任何超出这个范围的事情都会引起我的警报。

如何使用 Mock?

It might be a sign of high coupling - which in turn implies a need to reduce dependencies (which will improve design and testability). As a rough guideline, an object should have around 4-6 collaborators max. Anything over that would set off my alarms.

How are Mocks meant to be used?

与风相奔跑 2024-08-01 21:03:28

对我来说,这听起来像是无法测试的代码,这是一种味道:-(

我建议阅读 http: //misko.hevery.com/code-reviewers-guide/。作者是负责测试领域的 Google 开发人员的教练,他在文章中展示了如何编写可测试和不可测试的代码

。 :
Clean Code (Robert C. Martin) - 主要关注如何编写干净的(对应于可测试的)代码。
有效地处理遗留代码 (Michael Feather) - 展示了控制未经测试和不可测试的代码的方法。

To me it sounds like untestable code, which is a smell :-(

I would recommend reading http://misko.hevery.com/code-reviewers-guide/. The author is coach responsible for teaching google developers in the testing area. In the article he shows how you can write testable and untestable code.

Further recommended reading:
Clean Code (Robert C. Martin) - main focus on how to write clean (which corresponds to testable) code.
Working effectively with legacy code (Michael Feather) - shows ways to get untested and untestable code under control.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文