Skip to content

refactor-jasmine-vitest: Bare spyOn() migration silently changes test behavior - should emit .mockReturnValue(undefined) #33253

@spliffone

Description

@spliffone

Command

generate

Is this a regression?

  • Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was

No response

Description

The @schematics/angular:refactor-jasmine-vitest schematic migrates bare spyOn(obj, 'method') calls (no chained .and.* strategy) as a direct mechanical rename to vi.spyOn(obj, 'method').

This silently changes test behavior because the two APIs have opposite defaults. jasmine.spyOn(obj, 'method') original is never called, returns undefined while vi.spyOn(obj, 'method') calls through.

The major problem it requires significant effort to review the test base and adjust all tests after the migration was executed.

Minimal Reproduction

// Given the following Jasmine test:
it('should stub myMethod', () => {
  spyOn(service, 'myMethod');      // original is never called — returns undefined
  component.doSomething();
  expect(service.myMethod).toHaveBeenCalled();
});
// Running ng generate ä@schematics/angular:refactor-jasmine-vitestä currently produces:
it('should stub myMethod', () => {
  vi.spyOn(service, 'myMethod');   // original implementation now runs
  component.doSomething();
  expect(service.myMethod).toHaveBeenCalled();
});

Exception or Error

A bare spyOn(obj, 'method') without any .and.* chain should migrate to vi.spyOn(obj, 'method').mockReturnValue(undefined) to preserve Jasmine's stub-by-default semantics:

it('should stub myMethod', () => {
  vi.spyOn(service, 'myMethod').mockReturnValue(undefined); // original is not called
  component.doSomething();
  expect(service.myMethod).toHaveBeenCalled();
});

Your Environment

_                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/
    

Angular CLI       : 21.2.11
Angular           : 21.2.13
Node.js           : 24.15.0
Package Manager   : yarn 1.22.22
Operating System  : darwin arm64

┌───────────────────────────────────┬───────────────────┬───────────────────┐
│ Package                           │ Installed Version │ Requested Version │
├───────────────────────────────────┼───────────────────┼───────────────────┤
│ @angular/animations               │ 21.2.13           │ 21.2.13           │
│ @angular/build                    │ 21.2.11           │ 21.2.11           │
│ @angular/cdk                      │ 21.2.11           │ 21.2.11           │
│ @angular/cli                      │ 21.2.11           │ 21.2.11           │
│ @angular/common                   │ 21.2.13           │ 21.2.13           │
│ @angular/compiler                 │ 21.2.13           │ 21.2.13           │
│ @angular/compiler-cli             │ 21.2.13           │ 21.2.13           │
│ @angular/core                     │ 21.2.13           │ 21.2.13           │
│ @angular/forms                    │ 21.2.13           │ 21.2.13           │
│ @angular/language-service         │ 21.2.13           │ 21.2.13           │
│ @angular/platform-browser         │ 21.2.13           │ 21.2.13           │
│ @angular/platform-browser-dynamic │ 21.2.13           │ 21.2.13           │
│ @angular/router                   │ 21.2.13           │ 21.2.13           │
│ rxjs                              │ 7.8.2             │ 7.8.2             │
│ typescript                        │ 5.9.3             │ ~5.9.3            │
│ vitest                            │ 4.1.7             │ 4.1.7             │
│ webpack                           │ 5.101.3           │ 5.101.3           │
│ zone.js                           │ 0.15.1            │ 0.15.1            │
└───────────────────────────────────┴───────────────────┴───────────────────┘

Anything else relevant?

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions