dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.21k stars 1.57k forks source link

Breakpoints skipped in tests when injecting late initialized dependency. #55643

Open dastbayoo opened 5 months ago

dastbayoo commented 5 months ago

I was trying to debug a test and couldn't manage to get any of my breakpoints to pause so that I could investigate the local values or to debug the expect statements step by step. I boiled it down to a minimal scenario.

Steps to reproduce

  1. Create class A with a dependency B.
  2. Create a test class for A that declares a field of type B with late and initialize it in setUp.
  3. In a test method, inject the B instance to A's constructor, add a call to A's method and add a few more lines like print statements or expects.
  4. Add breakpoints for each code line in the test method and also add a breakpoint within A.
  5. Debug the test.

Expected results

All the breakpoints are hit and execution pauses for each of them.

Actual results

The first breakpoint that hits is the one within A, then the liner after the constructor call.

Code sample

uut.dart ```dart class B { void foo() {} } class A { B dependency; A(this.dependency); void bar() { print(""); } } ``` uut_test.dart ```dart void main() { late B dep; setUp(() { dep = B(); }); test('', () { A(dep).bar(); expect(true, true); }); } ```

I experimented with some variations, some of which make a difference, some don't:

  1. It doesn't matter if I use setUp or setUpAll
  2. If I remove the late keyword and initialize B immediately, yet reassign it in the setUp again, the issue is gone!
  3. If I inject "B()" the issue is gone (probably related to the observation above)
  4. If I split the test into
    var uut = A(dep);
    uut.bar();
    expect(true, true);

    then my breakpoint misses the assignment but hits the uut.bar().

Tested with Android Studio and Visual Studio code, to rule out an IDE issue. Also I enabled breaking on all thrown exceptions to ensure I'm not missing caught exception within the framework.

It sounds small but in my production code it didn't hit any code after the call to the tested method, so it missed all of my expect statements.

Screenshot

The "expect" breakpoint hits, the one above is missed ![Code screenshot](https://github.com/dart-lang/sdk/assets/43368060/4ce268ff-3711-458c-98e0-91080a068baa)

Running on _Dart SDK version: 3.3.1 (stable) (Wed Mar 6 13:09:19 2024 +0000) on "windowsx64"

alexmarkov commented 5 months ago

/cc @derekxu16

derekxu16 commented 5 months ago

Thank you for the detailed report, @dastbayoo! I believe that the problem that you're encountering is the same as https://github.com/dart-lang/sdk/issues/53376. The breakpoints all work as expected for me when using a locally-built SDK built from an up-to-date checkout of this repo. The fix for that issue is not available in any stable SDK release yet, but it will be available in the next stable release. The fix is currently available in all beta releases starting from 3.4.0-190.1.beta.

a-siva commented 5 months ago

@dastbayoo can you confirm if the problem is fixed for you after upgrading to 3.4.0-190.1.beta or if you wait for a week we will have a stable 3.4 against which you can try,