You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单元测试返回属性为<Closure: () => Type>且持续失败排查

问题现象

开展单元测试时,读取Service类属性做断言,所有属性的断言结果均返回闭包而非实际值,报错信息如下:

Expected: <X>
Actual: Closure: () => Type>

提前打印属性值可以看到输出符合预期(loggedInUser打印为null),项目使用stacked包实现依赖注入,相关报错截图如下:
问题报错截图

测试代码片段:

void main() {
  group('TestService Tests -', () {
    TestService sut;

    setUp(() {
      registerServices();
    });

    tearDown(() {
      unregisterServices();
    });
    group('Initialize -', () {
      test('Determine authpage type when not logged in', () async {
        sut = TestService();
        User? result = sut.loggedInUser;
        print('Sut is equal to ${sut.loggedInUser}');

        expect(() => result, null);
      });

被测Service代码片段:

class TestService {
  final AuthenticationService _firebaseAuth = locator<AuthenticationService>();
  final SharedPreferencesService _prefs = locator<SharedPreferencesService>();
  final Logger _log = getLogger('LoginAndUserService');

  User? _loggedInUser = null;
  User? get loggedInUser => _loggedInUser;
  late bool _firstTimeUsingApp;
  bool? get firstTimeUsingApp => _firstTimeUsingApp;
  LoginStatus _currentLoginStatus = LoginStatus.notInitialized;
  LoginStatus get currentLoginStatus => _currentLoginStatus;
}
根本原因

该问题和stacked依赖注入框架无关,是测试断言的写法错误:
expect方法的第一个参数需要传入待校验的实际值,但代码里传入的是() => result——这是Dart中无参匿名闭包的简写语法,传入的是一个函数对象,而非result变量存储的属性值,因此断言拿到的实际结果永远是闭包对象,和预期值不匹配。
expect前打印sut.loggedInUser能得到正确的null值,是因为打印时直接读取了属性值,没有包裹闭包。

修复方案
  • 修改断言语句,移除包裹值的闭包语法,直接传入待校验的值即可:
    // 错误写法
    // expect(() => result, null);
    
    // 正确写法1:使用提前赋值的result变量
    expect(result, null);
    
    // 正确写法2:直接读取属性传入,无需提前赋值给中间变量
    expect(sut.loggedInUser, null);
    
  • 额外注意:被测类中_firstTimeUsingApp是late bool类型,没有在构造函数中初始化,后续测试如果要访问firstTimeUsingApp属性,必须先执行对应初始化逻辑,否则会抛出延迟初始化异常。

内容的提问来源于stack exchange,提问作者Charlie Page

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 14:48:15