You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
`vi` in the examples below is imported directly from `vitest`. You can also use it globally, if you set `globals` to `true` in your [config](/config/).
542
+
You can mock an entire class with a single `vi.fn` call - since all classes are also functions, this works out of the box. Beware that currently Vitest doesn't respect the `new` keyword so the `new.target` is always `undefined` in the body of a function.
543
+
544
+
```ts
545
+
classDog {
546
+
name:string
547
+
548
+
constructor(name:string) {
549
+
this.name=name
550
+
}
551
+
552
+
static getType():string {
553
+
return'animal'
554
+
}
555
+
556
+
speak():string {
557
+
return'bark!'
558
+
}
559
+
560
+
isHungry() {}
561
+
feed() {}
562
+
}
563
+
```
564
+
565
+
We can re-create this class with ES5 functions:
566
+
567
+
```ts
568
+
const Dog =vi.fn(function (name) {
569
+
this.name=name
570
+
})
571
+
572
+
// notice that static methods are mocked directly on the function,
573
+
// not on the instance of the class
574
+
Dog.getType=vi.fn(() =>'mocked animal')
575
+
576
+
// mock the "speak" and "feed" methods on every instance of a class
577
+
// all `new Dog()` instances will inherit these spies
578
+
Dog.prototype.speak=vi.fn(() =>'loud bark!')
579
+
Dog.prototype.feed=vi.fn()
580
+
```
581
+
582
+
::: tip WHEN TO USE?
583
+
Generally speaking, you would re-create a class like this inside the module factory if the class is re-exported from another module:
584
+
585
+
```ts
586
+
import { Dog } from'./dog.js'
587
+
588
+
vi.mock(import('./dog.js'), () => {
589
+
const Dog =vi.fn()
590
+
Dog.prototype.feed=vi.fn()
591
+
// ... other mocks
592
+
return { Dog }
593
+
})
594
+
```
595
+
596
+
This method can also be used to pass an instance of a class to a function that accepts the same interface:
597
+
598
+
```ts
599
+
// ./src/feed.ts
600
+
function feed(dog:Dog) {
601
+
// ...
602
+
}
603
+
604
+
// ./tests/dog.test.ts
605
+
import { expect, test, vi } from'vitest'
606
+
import { feed } from'../src/feed.js'
607
+
608
+
const Dog =vi.fn()
609
+
Dog.prototype.feed=vi.fn()
610
+
611
+
test('can feed dogs', () => {
612
+
const dogMax =newDog('Max')
613
+
614
+
feed(dogMax)
615
+
616
+
expect(dogMax.feed).toHaveBeenCalled()
617
+
expect(dogMax.isHungry()).toBe(false)
618
+
})
619
+
```
544
620
:::
545
621
546
-
I want to…
622
+
Now, when we create a new instance of the `Dog` class its `speak` method (alongside `feed`) is already mocked:
547
623
548
-
### Spy on a `method`
624
+
```ts
625
+
const dog =newDog('Cooper')
626
+
dog.speak() // loud bark!
627
+
628
+
// you can use built-in assertions to check the validity of the call
629
+
expect(dog.speak).toHaveBeenCalled()
630
+
```
631
+
632
+
We can reassign the return value for a specific instance:
633
+
634
+
```ts
635
+
const dog =newDog('Cooper')
636
+
637
+
// "vi.mocked" is a type helper, since
638
+
// TypeScript doesn't know that Dog is a mocked class,
639
+
// it wraps any function in a MockInstance<T> type
640
+
// without validating if the function is a mock
641
+
vi.mocked(dog.speak).mockReturnValue('woof woof')
642
+
643
+
dog.speak() // woof woof
644
+
```
645
+
646
+
To mock the property, we can use the `vi.spyOn(dog, 'name', 'get')` method. This makes it possible to use spy assertions on the mocked property:
You can also spy on getters and setters using the same method.
659
+
:::
660
+
661
+
## Cheat Sheet
662
+
663
+
:::info
664
+
`vi` in the examples below is imported directly from `vitest`. You can also use it globally, if you set `globals` to `true` in your [config](/config/).
@@ -691,6 +793,10 @@ original() // has original behaviour
691
793
mocked() // is a spy function
692
794
```
693
795
796
+
::: warning
797
+
Don't forget that this only [mocks _external_ access](#mocking-pitfalls). In this example, if `original` calls `mocked` internally, it will always call the function defined in the module, not in the mock factory.
798
+
:::
799
+
694
800
### Mock the current date
695
801
696
802
To mock `Date`'s time, you can use `vi.setSystemTime` helper function. This value will **not** automatically reset between different tests.
@@ -762,6 +868,6 @@ it('the value is restored before running an other test', () => {
0 commit comments