验证 Mock 对象交互
当您创建 mock 时,还会创建一个用于控制 mock 行为的关联行为对象。使用此对象可访问所拦截的从受测组件发送到 mock 对象的消息(称为 spying 的进程)。有关创建 mock 的详细信息,请参阅创建 Mock 对象。
在模拟框架中,鉴定为用于测试与该对象的交互的函数。有四种鉴定类型:
确认 - 在不抛出异常的情况下产生并记录失败。由于确认不会抛出异常,因此即使出现确认失败的情形,依然会完成所有的测试内容。通常,确认是单元测试的主要鉴定类型,因为这些确认一般不要求提前从测试中退出。使用其他鉴定类型来测试是否违反前提条件或测试安装是否正确。
假设 - 确保测试环境满足前提条件,不会导致测试失败。假设失败会导致测试被滤除,且测试框架会将这些测试标记为未完成。
断言 - 确保失败条件会使当前测试内容的剩余部分失效,但不会阻止后续测试方法正常执行。断言点处的失败会将当前测试方法标记为失败且未完成。
致命断言 - 在失败时中止测试会话。当失败涉及根本以致没必要继续测试时,这种鉴定会很有用。当脚手架拆解未能正确还原 MATLAB® 状态,适合中止测试并启动一个新会话时,这些鉴定也很有用。
mock 对象是超类所指定接口的抽象方法和属性的实现。您也可以在没有超类的情况下构造 mock,在这种情况下,mock 具有一个隐式接口。为骰子类创建一个具有隐式接口的 mock。该接口包含 Color 和 NumSides 属性以及 roll 方法,后者接受骰子数并返回一个值。虽然该接口当前未实现,但您可以创建一个具有该接口的 mock。
testCase = matlab.mock.TestCase.forInteractiveUse; [mock,behaviorObj] = testCase.createMock('AddedProperties', ... {'NumSides','Color'},'AddedMethods',{'roll'});
验证 Mock 方法交互
由于 mock 会记录向其发送的交互,因此您可以验证是否调用了 mock 方法。掷一个骰子。
val = mock.roll(1);
验证是否使用了 1 个骰子调用 roll 方法。
testCase.verifyCalled(behaviorObj.roll(1))
Interactive verification passed.
验证是否使用了 3 个骰子调用 roll 方法。此测试将失败。
testCase.verifyCalled(behaviorObj.roll(3), ... 'roll method should have been called with input 3.')
Interactive verification failed.
----------------
Test Diagnostic:
----------------
roll method should have been called with input 3.
---------------------
Framework Diagnostic:
---------------------
verifyCalled failed.
--> Method 'roll' was not called with the specified signature.
--> Observed method call(s) with any signature:
out = roll([1×1 matlab.mock.classes.Mock], 1)
Specified method call:
MethodCallBehavior
[...] = roll(<Mock>, 3)验证是否未使用 2 个骰子调用 roll 方法。
testCase.verifyNotCalled(behaviorObj.roll(2))
Interactive verification passed.
由于 MethodCallBehavior 类的 withAnyInputs、withExactInputs 和 withNargout 方法会返回 MethodCallBehavior 对象,因此您可以在鉴定中使用这些方法。验证是否使用了任何输入至少调用一次 roll 方法。
testCase.verifyCalled(withAnyInputs(behaviorObj.roll))
Interactive verification passed.
验证是否未使用 2 个输出和任何输入调用 roll 方法。
testCase.verifyNotCalled(withNargout(2,withAnyInputs(behaviorObj.roll)))
Interactive verification passed.
验证 Mock 属性交互
与方法调用类似,mock 会记录属性设置和访问操作。设置骰子的颜色。
mock.Color = "red"mock =
Mock with properties:
NumSides: []
Color: "red"验证是否设置了颜色。
testCase.verifySet(behaviorObj.Color)
Interactive verification passed.
验证是否对颜色进行了访问。此测试将通过,因为在 MATLAB 显示该对象时会隐式访问属性。
testCase.verifyAccessed(behaviorObj.Color)
Interactive verification passed.
断言未设置面数。
testCase.assertNotSet(behaviorObj.NumSides)
Interactive assertion passed.
使用 Mock 对象约束
matlab.mock.TestCase 方法便于监视 mock 交互。但是,如果您改用 matlab.mock.constraints 命名空间中的类,则有更多功能可供使用。要使用约束,请将行为对象和约束传递给 verifyThat、assumeThat、assertThat 或 fatalAssertThat 方法。
创建一个新的 mock 对象。
testCase = matlab.mock.TestCase.forInteractiveUse; [mock,behaviorObj] = testCase.createMock('AddedProperties', ... {'NumSides','Color'},'AddedMethods',{'roll'});
掷 2 个骰子。然后,通过约束来验证是否使用了两个骰子至少调用一次 roll 方法。
val = mock.roll(2);
import matlab.mock.constraints.WasCalled
testCase.verifyThat(behaviorObj.roll(2),WasCalled)Interactive verification passed.
掷一个骰子。然后,验证是否使用了任何输入至少调用两次 roll 方法。
val = mock.roll(1); testCase.verifyThat(withAnyInputs(behaviorObj.roll), ... WasCalled('WithCount',2))
Interactive verification passed.
验证是否未访问 NumSides。
import matlab.mock.constraints.WasAccessed
testCase.verifyThat(behaviorObj.NumSides,~WasAccessed)Interactive verification passed.
设置骰子的颜色。然后,验证是否将该属性设置了一次。
mock.Color = "blue"; import matlab.mock.constraints.WasSet testCase.verifyThat(behaviorObj.Color,WasSet('WithCount',1))
Interactive verification passed.
访问 Color 属性。然后,验证该属性是否未正好访问一次。此测试将失败。
c = mock.Color
testCase.verifyThat(behaviorObj.Color,~WasAccessed('WithCount',1))c =
"blue"
Interactive verification failed.
---------------------
Framework Diagnostic:
---------------------
Negated WasAccessed failed.
--> Property 'Color' was accessed the prohibited number of times.
Actual property access count:
1
Prohibited property access count:
1
Specified property access:
PropertyGetBehavior
<Mock>.Color设置面数。然后,验证面数是否设置为 22。
mock.NumSides = 22;
testCase.verifyThat(behaviorObj.NumSides,WasSet('ToValue',22))Interactive verification passed.
使用 matlab.unittest.constraints 命名空间中的约束来断言骰子的面数未被设置为超过 20。此测试将失败。
import matlab.unittest.constraints.IsLessThanOrEqualTo testCase.verifyThat(behaviorObj.NumSides, ... WasSet('ToValue',IsLessThanOrEqualTo(20)))
Interactive verification failed.
---------------------
Framework Diagnostic:
---------------------
WasSet failed.
--> Property 'NumSides' was not set to the specified value.
--> Observed property set(s) to any value:
<Mock>.NumSides = 22
Specified property set:
PropertySetBehavior
<Mock>.NumSides = <IsLessThanOrEqualTo constraint>鉴定概述
| 鉴定类型 | TestCase 方法 | matlab.mock.constraints 类 | |
|---|---|---|---|
使用 matlab.unittest.TestCase 方法 | 通过 matlab.mock.constraints 类 | ||
| 已调用方法 | verifyCalled 或 verifyNotCalled | verifyThat | WasCalled 或 Occurred |
assumeCalled 或 assumeNotCalled | assumeThat | ||
assertCalled 或 assertNotCalled | assertThat | ||
fatalAssertCalled 或 fatalAssertNotCalled | fatalAssertThat | ||
| 方法已被调用特定次数 | 不适用 | verifyThat、assumeThat、assertThat 或 fatalAssertThat | WasCalled |
| 已访问属性 | verifyAccessed 或 verifyNotAccessed | verifyThat | WasAccessed 或 Occurred |
assumeAccessed 或 assumeNotAccessed | assumeThat | ||
assertAccessed 或 assertNotAccessed | assertThat | ||
fatalAssertAccessed 或 fatalAssertNotAccessed | fatalAssertThat | ||
| 属性已被访问特定次数 | 不适用 | verifyThat、assumeThat、assertThat 或 fatalAssertThat | WasAccessed |
| 已设置属性 | verifySet 或 verifyNotSet | verifyThat | WasSet 或 Occurred |
assumeSet 或 assumeNotSet | assumeThat | ||
assertSet 或 assertNotSet | assertThat | ||
fatalAssertSet 或 fatalAssertNotSet | fatalAssertThat | ||
| 属性已被设置特定次数 | 不适用 | verifyThat、assumeThat、assertThat 或 fatalAssertThat | WasSet |
| 属性已被设置为特定值 | 不适用 | verifyThat、assumeThat、assertThat 或 fatalAssertThat | WasSet 或 Occurred |
| 按特定顺序调用方法并访问或设置属性 | 不适用 | verifyThat、assumeThat、assertThat 或 fatalAssertThat | Occurred |