122 lines
3.8 KiB
Dart
122 lines
3.8 KiB
Dart
|
|
// 功能描述:充值先存后发和未确认订单保留;版本:1.0.0。
|
|||
|
|
import 'package:flutter_test/flutter_test.dart';
|
|||
|
|
import 'package:user_app/data/services/recharge_draft_store.dart';
|
|||
|
|
import 'package:user_app/data/services/recharge_flow.dart';
|
|||
|
|
import 'package:user_app/data/services/api_client.dart';
|
|||
|
|
import 'package:user_app/domain/models/recharge.dart';
|
|||
|
|
import '../support/a1_fixture.dart';
|
|||
|
|
|
|||
|
|
class _Store implements RechargeDraftStore {
|
|||
|
|
PendingRecharge? value;
|
|||
|
|
bool fail = false;
|
|||
|
|
@override
|
|||
|
|
Future<PendingRecharge?> read(String owner) async => value;
|
|||
|
|
@override
|
|||
|
|
Future<void> write(String owner, PendingRecharge draft) async {
|
|||
|
|
if (fail) throw StateError('存储失败');
|
|||
|
|
value = draft;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@override
|
|||
|
|
Future<void> delete(String owner) async {
|
|||
|
|
value = null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class _Repo extends A1FixtureRepository {
|
|||
|
|
_Repo(this.store);
|
|||
|
|
final _Store store;
|
|||
|
|
int calls = 0, status = 10;
|
|||
|
|
int? queryError;
|
|||
|
|
String owner = 'api#alice';
|
|||
|
|
bool changeOwnerOnQuery = false;
|
|||
|
|
@override
|
|||
|
|
Future<String> rechargeDraftOwner() async => owner;
|
|||
|
|
@override
|
|||
|
|
Future<Map<String, Object?>> createRecharge({
|
|||
|
|
required String request,
|
|||
|
|
required int amount,
|
|||
|
|
required String channel,
|
|||
|
|
required String payType,
|
|||
|
|
}) async {
|
|||
|
|
expect(store.value?.request, request);
|
|||
|
|
calls++;
|
|||
|
|
throw StateError('响应丢失');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@override
|
|||
|
|
Future<RechargeRecord> rechargeResult(String request) async {
|
|||
|
|
if (changeOwnerOnQuery) owner = 'api#bob';
|
|||
|
|
if (queryError != null) throw ApiException(queryError!, '查询失败');
|
|||
|
|
return RechargeRecord(
|
|||
|
|
identity: 'order',
|
|||
|
|
number: request,
|
|||
|
|
amount: 100,
|
|||
|
|
status: status,
|
|||
|
|
channel: 'alipay',
|
|||
|
|
createdAt: DateTime(2026),
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void main() {
|
|||
|
|
test('明确不存在可原号重发,网络错误和账号切换不能发单', () async {
|
|||
|
|
const draft = PendingRecharge(
|
|||
|
|
request: 'request-1',
|
|||
|
|
amount: 100,
|
|||
|
|
channel: 'alipay',
|
|||
|
|
payType: 'wap',
|
|||
|
|
);
|
|||
|
|
for (final code in [1112, 500]) {
|
|||
|
|
final store = _Store()..value = draft;
|
|||
|
|
final repo = _Repo(store)..queryError = code;
|
|||
|
|
final flow = RechargeFlow(repo, store);
|
|||
|
|
await expectLater(
|
|||
|
|
flow.create(draft),
|
|||
|
|
code == 1112
|
|||
|
|
? throwsStateError
|
|||
|
|
: throwsA(isA<ApiException>().having((e) => e.code, '错误码', 500)),
|
|||
|
|
);
|
|||
|
|
expect(repo.calls, code == 1112 ? 1 : 0);
|
|||
|
|
expect(store.value?.request, draft.request);
|
|||
|
|
}
|
|||
|
|
final store = _Store()..value = draft;
|
|||
|
|
final repo = _Repo(store)..changeOwnerOnQuery = true;
|
|||
|
|
await expectLater(RechargeFlow(repo, store).create(draft), throwsStateError);
|
|||
|
|
expect(repo.calls, 0);
|
|||
|
|
expect(store.value, isNotNull);
|
|||
|
|
});
|
|||
|
|
test('存储失败不发单,响应丢失保留原请求,到账后才清除', () async {
|
|||
|
|
final store = _Store()..fail = true;
|
|||
|
|
final repo = _Repo(store);
|
|||
|
|
final flow = RechargeFlow(repo, store);
|
|||
|
|
const draft = PendingRecharge(
|
|||
|
|
request: 'request-1',
|
|||
|
|
amount: 100,
|
|||
|
|
channel: 'alipay',
|
|||
|
|
payType: 'wap',
|
|||
|
|
);
|
|||
|
|
await expectLater(flow.create(draft), throwsStateError);
|
|||
|
|
expect(repo.calls, 0);
|
|||
|
|
store.fail = false;
|
|||
|
|
await expectLater(flow.create(draft), throwsStateError);
|
|||
|
|
expect(repo.calls, 1);
|
|||
|
|
expect(store.value?.request, 'request-1');
|
|||
|
|
await expectLater(
|
|||
|
|
flow.create(
|
|||
|
|
const PendingRecharge(request: 'request-2', amount: 100, channel: 'alipay', payType: 'wap'),
|
|||
|
|
),
|
|||
|
|
throwsStateError,
|
|||
|
|
);
|
|||
|
|
expect(repo.calls, 1);
|
|||
|
|
expect((await flow.recover())?.credited, isFalse);
|
|||
|
|
expect(store.value, isNotNull);
|
|||
|
|
repo.status = 23;
|
|||
|
|
expect(await flow.create(draft), {'recharge_status': 23});
|
|||
|
|
expect(repo.calls, 1);
|
|||
|
|
expect(store.value, isNotNull);
|
|||
|
|
expect((await flow.recover())?.credited, isTrue);
|
|||
|
|
expect(store.value, isNull);
|
|||
|
|
});
|
|||
|
|
}
|