/*
* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* This source file is part of the Cangjie project, licensed under Apache-2.0
* with Runtime Library Exception.
*
* See https://cangjie-lang.cn/pages/LICENSE for license information.
*/
// The Cangjie API is in Beta. For details on its capabilities and limitations, please refer to the README file.
package std.unittest.mock
/**
* Part of stub chain. Specifies cardinality of an action that comes immediately before it in the stub chain.
*
* Cardinality can imply verification to be done by the framework:
* Stubs invoked more times than specified will throw ExpectationFailedException immediately.
* For stubs that were not invoked enough times framework will throw ExpectationFailedException after code under test finished executing.
*/
public class CardinalitySelector<A> where A <: ActionSelector {
CardinalitySelector(
let sc: Scenario,
let factory: (Scenario) -> A
) {}
/**
* Specifies that the stub can be invoked any number of times.
* There are no expectations for this stub.
*/
public func anyTimes(): Unit {
sc.setCardinality(Cardinality.atLeastTimes(0))
}
/**
* Specifies that the stub must be invoked exactly one time.
* @return continuation representing additional actions to be performed when conditions were satisfied.
*/
public func once(): Continuation<A> {
sc.setCardinality(Cardinality.once())
Continuation<A>(sc, factory)
}
/**
* Specifies that the stub must be invoked at least one time.
*/
public func atLeastOnce(): Unit {
sc.setCardinality(Cardinality.atLeastOnce())
}
/**
* Specifies that the stub must be invoked an exact number of times.
* @param expectedTimes number of times stub must be invoked.
* @return continuation representing additional actions to be performed when conditions were satisfied.
*/
public func times(expectedTimes: Int64): Continuation<A> {
sc.setCardinality(Cardinality.times(expectedTimes))
Continuation<A>(sc, factory)
}
/**
* Specifies that the stub must be invoked [min..max] times.
* @param min minimum number of times the stub must be invoked.
* @param max maximum number of times the stub must be invoked.
* @return continuation representing additional actions to be performed when conditions were satisfied.
*/
public func times(min!: Int64, max!: Int64): Unit {
sc.setCardinality(Cardinality.times(min: min, max: max))
}
/**
* Specifies that the stub must be invoked at least certain number of times.
* @param minTimesExpected minimum number of times the stub must be called.
*/
public func atLeastTimes(minTimesExpected: Int64): Unit {
sc.setCardinality(Cardinality.atLeastTimes(minTimesExpected))
}
}
/**
* Part of the stub chain. Allows to specify additional action will be performed
* by the stub when previous actions cardinality will be satisfied.
* Specifying continuation only makes sense if it is followed by an action.
* MockFrameworkException will be thrown if there are any unfinished stub chains.
* No guarantees are given on exact point this exception will be thrown.
*/
public class Continuation<A> where A <: ActionSelector {
Continuation(
let previousSc: Scenario,
let factory: (Scenario) -> A
) {}
/**
* @return an ActionSelector for an action to be performed when previous actions in the chain are completed.
*/
public func then(): A {
let continuationSc = MockFramework.session {
session: MockSession => previousSc.parentChain.addScenario(session)
}
factory(continuationSc)
}
}