验证 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 |