首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 互联网 >

Jmockit用户指南中文翻译(未审校)之三

2012-06-30 
Jmockit用户指南中文翻译(未校对)之三严格和非严格的期望在期望块new Expectations(){...}中,默认所有被记

Jmockit用户指南中文翻译(未校对)之三
严格和非严格的期望

在期望块new Expectations(){...}中,默认所有被记录下来的期望都是严格的。这意味着,这些期望的调用必须在重播阶段被执行,而且需要按照声明的期望指定的执行顺序执行,而且,也只允许这些调用被执行。任何一个没有被记录下来的非期望调用都会造成测试用例失败。

另一方面,当我们需要记录(录制)非严格(或者是松散)的期望时,那么我们可以使用mockit.NonStrictExpectations子类。在一个非严格的期望块中,所有的被mock的类型的所有调用都可以在重播阶段执行,当然包括不在期望中声明的。也就是说,默认情况下,在重播阶段是否执行mock类型的调用是不会造成测试用例失败的。同样,这种不严格的期望是不要求调用的执行顺序的。

缺省情况下,一个严格的期望会精确匹配重播阶段的一个调用。换而言之,这类型的期望是存在一个隐式的调用次数约束1,就好像它后面紧跟着times=1这个约束。而另一方面,对于一个非严格的期望,默认是可以匹配重播阶段调用的任意次数的。它存在一个隐式的调用次数下限为0的约束,就好像,被指定约束minTimes=0.然而,无论哪种情况,隐式的调用次数约束是可以被显式的约束(相当于使用times/minTimes/maxTimes 属性字段)覆盖的。所以,一个严格的期望也可以被设置成允许任何调用次数的约束,同样,非严格的期望约束也可以反过来(当然,其前提是我们确实需要这样)。

请注意,对于一个严格的期望,所有在重播阶段被期望所匹配的调用,都会隐式被校验通过的。剩余的调用则被认为不符合期望(即造成测试失败),除非,这个mock的类型被关联到一个非严格的期望上。所以,使用隐式验证的严格期望需要排除verification块的使用,这个块是用于调用的显式校验的。实际上,在 new Verifications() {...}代码块中,只有那些匹配非严格期望的调用才被允许使用。同样,那些非严格的mock类型中的调用(没有被期望声明的)也可以显式记录。

为了允许在new Expectations(){...}代码块中混合使用严格和非严格调用,我们提供了一个mockit.NonStric注解用于mock属性域或者参数。任何一个这样的mock类型都可以被认为是一个非严格期望,同时所有没有被录制的调用都可以运行在重播阶段执行(就是说,它们不被认为是非期望的执行,因此不会造成测试失败)。这是特别有用的,以避免需要记录调用构造函数,或任何不感兴趣的方法。

在一个期望代码块中,一个独立的期望可以通过在调用语句后加上notStrict()方法将该期望标记为非严格期望,尽管在大多数情况下,使用non-strict期望块或者使用non-strict注解mock字段/参数会比这种方式更容易简单。

因此,对于给定一个测试,我们怎么在严格和非严格期望之间进行选择呢?这里没有普遍正确的答案。这通常会依赖于当前单元测试的特点以及个人的经验。总之,请谨记在脑袋的是,一个测试是可以同时混合使用这两种期望的,因此我们可以灵活的使用它们。

Strict and non-strict mocks 严格和非严格mock

通常来说,我们最好站在一个独立的期望角度来思考使用严格性,而不是在一个mock实例或者类型上面考虑。等价的说法是,对于一个给定的mock实例(或者类型)要么是严格的要么是非严格的。这意味着,特定实例/类型相关联的所有期望有相同的严格性。另一方面,在相同的测试,同时记录相同的mock实例或类型的严格和非严格的期望,是完全有效的。而当使用在测试类级别声明的mock字段时,一个给定的mock实例在一个测试用例中是完全严格的,而同时,在同一个测试类中,在另一个测试用例中,却是不严格的,这种情况是可以存在的。

总结下,我们可以指定三种不同严格性的方式:1)在一个给定的严格期望块中,如果需要指定某一个期望是非严格的,可以调用notStrict()方法。2)对于一个特殊的mock类型/实例,其所有期望都需要是完全非严格的,则可以通过注解@NonStrict将其声明为一个mock属性字段或者参数。3)如果在一个期望块中,需要所有的期望都是非严格的,则可以使用NonStrictExpectations类。

另一方面,这里没有提供任何一种方式去显式的指定某个给定的期望、mock类型/实例、或者一个完整的期望块应该是严格的。当我们没有指定期望是非严格时,被记录下来的期望都被缺省认为是严格的。因此,对于一个期望需要被声明为严格时,它应该被记录在不在NonStrictExpectations的期望expectation中,而对于mock类型,则不应该被注解为 @NonStrict. 而关联的mock类型和它相对应的所有实例都会被作为一个整体进行严格的校验,除了哪些匹配到一个被显式标记为非严格的调用。

最后,请注意,如果对于一个给定的Mock类型,在测试代码中没有任何相应的期望被记录,那么这个mock类型会自动被认为是一个完全不严格的(就好像这个mock的字段/参数被注解为 @NonStrict).

Iterated expectations 迭代期望
当一系列有序连续的调用被记录在一个严格期望块中(调用之间的相对顺序与非严格的期望是无关的),整个序列则被期望在重播阶段执行。然而,让我们考虑下这种情况,这些调用是在测试代码中的一个循环(或者任何其他迭代方式)里面执行。假设在测试代码中,我们是可以预先知道迭代次数,那么我们仍然记录这些期望,匹配这些将在循环中执行的方法/构造函数(注意,我们并不是在一个期望代码块中,通过循环的方式声明调用期望)。通过使用Expectations(int numberOfIterations)构造函数,下面的demo显示了这种特性。
Full verification 完整校验
有时候,对mock类型所有的调用进行校验可能是很重要的。这自然就是记录严格期望时的情况,因为任何一个不希望发生的调用被执行都会造成测试失败。当在非严格期望中使用显式的校验时,可以使用new FullVerifications() {...}块来确保没有调用未被校验。
?

?

上面使用两个verification验证块目的是用来解释有序和无序的迭代验证的区别。在第一个验证块中,每一个验证调用都必须至少重播阶段中相同方法3次,因为迭代次数被传递到构造函数里。对于无序的迭代块,指定迭代次数会用来乘以下限和上限的调用次数,当在验证块内指定一个明确的约束,如一个minTimes= 1; maxTimes= 4,就会被乘以迭代次数;在上面的例子中就相当于被各自被乘以3,转化成minTimes= 3; maxTimes= 12;.另一方面,在第二个验证块中,调用次数的约束则无效。相反,产生的效果相当于"展开循环",就好像验证块校验调用的重复每个迭代。

迭代的FullVerifications块的语义和正常的校验块是一样的。迭代FullVerificationsInOrder块和一个VerificationsInOrder块也是一样。

热点排行