5

我有一个类 API,它具有完整的代码覆盖率,并使用 DI 来模拟完成所有工作的主类函数 (Job.Run) 中的所有逻辑。

我在生产中发现了一个错误,我们没有对其中一个数据输入字段进行一些验证。

所以,我添加了一个名为 ValidateFoo() 的存根函数...针对这个函数编写了一个单元测试来期望 JobFailedException,运行测试 - 它显然失败了,因为该函数是空的。我添加了验证逻辑,现在测试通过了。

太好了,现在我们知道验证有效。问题是 - 我如何编写测试以确保在 Job.Run() 中实际调用了 ValidateFoo()?ValidateFoo() 是 Job 类的私有方法 - 所以它不是一个接口......

无论如何用 NMock2.0 做这个?我知道 TypeMock 支持非接口类型的假货。但是现在更改模拟库不是一种选择。在这一点上,如果 NMock 不能支持它,我只需将 ValidateFoo() 调用添加到 Run() 方法并手动测试 - 考虑到我的 Job.Run() 方法显然我不想这样做现在100%覆盖。有什么建议吗?非常感谢,非常感谢。

编辑:我想到的另一个选择是为我的 Job.Run 功能创建一个集成测试(向它注入复合对象的真正实现而不是模拟)。我将为该字段提供一个错误的输入值,然后验证作业是否失败。这有效并涵盖了我的测试 - 但它不是真正的单元测试,而是测试一个功能单元的集成测试......嗯......

EDIT2:有什么办法可以做到吗?有人有想法吗?也许 TypeMock - 或者更好的设计?

4

2 回答 2

5

当前版本的 NMock2可以使用最熟悉的语法模拟具体类型(我不记得他们添加的确切版本,但我们使用的是 2.1 版本):

Job job = mockery.NewMock<Job>(MockStyle.Transparent);
Stub.On(job).Method("ValidateFoo").Will(Return.Value(true));

MockStyle.Transparent 指定您不存根或期望的任何内容都应由底层实现处理 - 因此您可以存根并为正在测试的实例上的方法设置期望。

但是,您只能对公共方法(和属性)进行存根和设置期望,这些方法也必须是虚拟的或抽象的。因此,为了避免依赖集成测试,您有两种选择:

  • Job.ValidateFoo()公开和虚拟。
  • 将验证逻辑提取到一个新类中并将一个实例注入到Job.
于 2010-04-26T17:13:43.517 回答
1

Since all private are all called by public methods (unless relying on reflection runtime execution), then those privates are being executed by public methods. Those private methods are causing changes to the object beyond simply executing code, such as setting class fields or calling into other objects. I'd find a way to get at those "results" of calling the private method. (Or mocking the things that shouldn't be executed in the private methods.)

I can't see the class under test. Another problem that could be pushing you to want access to the private methods is that it's a super big class with a boatload of private functionality. These classes may need to be broken down into smaller classes, and some of those privates may turn into simpler publics.

于 2011-03-23T22:48:45.860 回答