Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Modern Testing in Angular with Vitest
Search
Fabian Gosebrink
October 22, 2026
Technology
47
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Modern Testing in Angular with Vitest
Fabian Gosebrink
October 22, 2026
More Decks by Fabian Gosebrink
See All by Fabian Gosebrink
Mastering State Management in Angular: Demystifying NgRx, the Signal Store, and Events Plugin
fabiangosebrink
0
23
The Psychology of Overengineering
fabiangosebrink
0
29
Why State Is the Most Important Part of Your Angular Application
fabiangosebrink
0
49
Scalable Angular Architectures with Route-Based Architecture
fabiangosebrink
0
47
Advanced Signal Store: Structuring State for Real Angular Applications
fabiangosebrink
0
140
NgRx Signal Store - A Deeper Dive
fabiangosebrink
0
92
Modern Angular Apps in 2026
fabiangosebrink
0
170
Why State is the Most Important Part of Your Angular Application
fabiangosebrink
0
180
Angular testing made easy with Jest and Cypress
fabiangosebrink
0
200
Other Decks in Technology
See All in Technology
DBTS2026 盛り上がってますか!?Databricksが実現するAI時代のデータ基盤
akuwano
1
200
Kiro CLI 入門 (ターミナルと CI で使う) | 目指せ Kiro マスター 03
inariku
PRO
2
130
AWS Quick 入門 | 目指せ Quick マスター 01
inariku
PRO
2
300
The future of architectural work
ufried
0
200
少ない人手 限られた予算 それでも守る 消せない・見つける・戻れる オールハザード型BCP on AWS / 20261107 Mitsutoshi Matsuo
shift_evolve
PRO
0
350
Content Mapper APIの応用例~CSS Modules、言語ファイル~
uhyo
2
640
令和の今、あらためて IAM を考える。アクセスキーを「無くせない現実」との向き合い方
kazzpapa3
0
600
公共分野での生成AI活用
toru_kubota
1
320
Kiro IDE 入門 (画面の各部から、頼み方、任せ方、戻し方まで) | 目指せ Kiro マスター 02
inariku
PRO
4
200
Kiro Crew の Bot (続く役目を任せる窓口) | 目指せ Kiro マスター 12
inariku
PRO
2
360
業務でAWSをあまり使っていない私が、AWSへのモチベを保つ方法
smt7174
0
190
レガシーコードに対する loop engineering的なAI開発プロセス導入について
kubell_hr
0
330
Featured
See All Featured
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
630
A Tale of Four Properties
chriscoyier
163
24k
GraphQLとの向き合い方2022年版
quramy
50
15k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
Why Our Code Smells
bkeepers
PRO
340
58k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
980
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
630
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
400
How to Ace a Technical Interview
jacobian
280
24k
Technical Leadership for Architectural Decision Making
baasie
4
640
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
203
77k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
530
Transcript
Angular Testing Ensure the reliability of your Angular applications with
robust unit and integration testing strategies using testing tools.
Types of testing
Types of testing Unit Testing
Types of testing Unit Testing Shallow Testing
Types of testing Unit Testing Shallow Testing Integration Testing
Types of testing Unit Testing Shallow Testing Integration Testing End
to End Testing
Testing Strategies
Testing Strategies As small as possible
Testing Strategies As small as possible Readable
Testing Strategies As small as possible Readable Mocking friendly
Testing Strategies As small as possible Readable Mocking friendly Test
driven
Testing Strategies
Testing Strategies Clean Components
Testing Strategies Clean Components Most important part As little logic
as possible
Testing Strategies 1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 ✓ Easy to test: container @Component({ selector: 'lib-main-dog', templateUrl: './main-dog.component.html', styleUrls: ['./main-dog.component.scss'], providers: [MainDogStore], imports: [DogListComponent, DogRateComponent], }) export class MainDogComponent { dogId = input(''); store = inject(MainDogStore); constructor() { this.store.selectDog(this.dogId); } }
Testing Strategies 1 2 3 4 5 6 7 8
9 10 ✓ Easy to test: presentational @Component({ selector: 'lib-dog-list', templateUrl: './dog-list.component.html', styleUrls: ['./dog-list.component.scss'], }) export class DogListComponent { dogs = input<Dog[]>([]); dogSelected = output<string>(); }
Testing Strategies ✗ Hard to test: too much logic 1
@Component({ 2 selector: 'app-products', 3 imports: [ProductCategoryComponent, CategoryNamePipe], 4 templateUrl: './products.component.html', 5 styleUrl: './products.component.scss', 6 }) 7 export class ProductsComponent implements OnInit { 8 products = signal<{ category: string; products: Product[] }[]>([]); 9 private readonly productsService = inject(ProductsService); private readonly checkoutService = inject(CheckoutService); 10 11 private readonly toastrService = inject(ToastrService); 12 private readonly router = inject(Router); 13 ngOnInit() { 14 this.productsService.loadProducts().subscribe((products) => { 15 16 const categoryProductMap = products.reduce( 17 (result: Record<string, Product[]>, product) => { 18 const category = product.category; 19 20 if (!result[category]) {
Testing Strategies ✗ Hard to test: too much logic 1
@Component({ 2 selector: 'app-products', 3 imports: [ProductCategoryComponent, CategoryNamePipe], 4 templateUrl: './products.component.html', 5 styleUrl: './products.component.scss', 6 }) 7 export class ProductsComponent implements OnInit { 8 products = signal<{ category: string; products: Product[] }[]>([]); 9 private readonly productsService = inject(ProductsService); private readonly checkoutService = inject(CheckoutService); 10 11 private readonly toastrService = inject(ToastrService); 12 private readonly router = inject(Router); 13 14 ngOnInit() { 15 this.productsService.loadProducts().subscribe((products) => { 16 const categoryProductMap = products.reduce( 17 (result: Record<string, Product[]>, product) => { 18 const category = product.category; 19 20 if (!result[category]) {
Testing Strategies ✗ Hard to test: too much logic 1
@Component({ 14 ngOnInit() { 2 selector: 'app-products', 15 this.productsService.loadProducts().subscribe((products) => { 16 3 imports: CategoryNamePipe], const[ProductCategoryComponent, categoryProductMap = products.reduce( 17 4 templateUrl: './products.component.html', (result: Record<string, Product[]>, product) => { 5 styleUrl: './products.component.scss', 18 const category = product.category; 19 6 }) 20 7 export class ProductsComponent implements OnInit { if (!result[category]) { 21 8 products =result[category] signal<{ category: string; products: Product[] }[]>([]); = []; 22 9 private } readonly productsService = inject(ProductsService); 23 private readonly checkoutService = inject(CheckoutService); 10 24 11 private result[category].push(product); readonly toastrService = inject(ToastrService); 25 12 private readonly router = inject(Router); 26 13 return result; 27 }, 14 ngOnInit() { 28 15 this.productsService.loadProducts().subscribe((products) {}, => { 29 ); 16 const categoryProductMap = products.reduce( 30 17 (result: Record<string, Product[]>, product) => { 31 18 const const groupedByCategory category = product.category; = Object.keys(categoryProductMap).map( 32 19 (category) => ({ 33 20 if (!result[category]) { category,
Testing Strategies 32 1 33 2 34 3 35 4
36 5 37 6 38 7 39 8 40 9 41 10 42 11 43 12 44 13 45 14 46 15 47 16 48 17 49 18 50 19 51 20 ✗ Hard to test: too much logic (category) => ({ @Component({ category, selector: 'app-products', products: categoryProductMap[category], imports: [ProductCategoryComponent, CategoryNamePipe], }), templateUrl: './products.component.html', ); styleUrl: './products.component.scss', }) this.products.set(groupedByCategory); export class ProductsComponent implements OnInit { }); products = signal<{ category: string; products: Product[] }[]>([]); } private readonly productsService = inject(ProductsService); private readonly checkoutService = inject(CheckoutService); onProductClicked(id: string): void { private readonly toastrService = inject(ToastrService); this.router.navigate(['products', id]); private readonly router = inject(Router); } ngOnInit() { onCartClicked(product: Product): void { this.productsService.loadProducts().subscribe((products) => { this.checkoutService.addToCart(product).subscribe(() => { const categoryProductMap = products.reduce( this.toastrService.success('Item Added to Cart'); (result: Record<string, Product[]>, product) => { }); const category = product.category; } } if (!result[category]) {
Testing Strategies 32 1 33 2 34 3 35 4
36 5 37 6 38 7 39 8 40 9 41 10 42 11 43 12 44 13 45 14 46 15 47 16 48 17 49 18 50 19 51 20 ✗ Hard to test: too much logic (category) => ({ @Component({ category, selector: 'app-products', products: categoryProductMap[category], imports: [ProductCategoryComponent, CategoryNamePipe], }), templateUrl: './products.component.html', ); styleUrl: './products.component.scss', }) this.products.set(groupedByCategory); export class ProductsComponent implements OnInit { }); products = signal<{ category: string; products: Product[] }[]>([]); } private readonly productsService = inject(ProductsService); private readonly checkoutService = inject(CheckoutService); onProductClicked(id: string): void { private readonly toastrService = inject(ToastrService); this.router.navigate(['products', id]); private readonly router = inject(Router); } ngOnInit() { onCartClicked(product: Product): void { this.productsService.loadProducts().subscribe((products) => { this.checkoutService.addToCart(product).subscribe(() => { const categoryProductMap = products.reduce( this.toastrService.success('Item Added to Cart'); (result: Record<string, Product[]>, product) => { }); const category = product.category; } } if (!result[category]) {
Testing Tools
Testing Tools
Testing Syntax describe(...) // summarizes multiple tests test(...) // declares
a test it(...) // declares a test beforeEach(...) // runs before every test afterEach(...) // runs after every test
Testing Syntax describe('1st tests', () => { it('true is true',
() => { expect(true).toBe(true); }); });
Testing Example - Pipe import { FilterPipe } from './filter.pipe';
describe('FilterPipe', () => { let filterPipe: FilterPipe; // synchronous beforeEach beforeEach(() => { filterPipe = new FilterPipe(); }); it('filterPipe should be instantiated', () => { // ... }); it('filterPipe should filter', () => { // ... }); });
Arrange Act Assert
Testing Assertions expect(…).toBe(…); // Assert // Matcher toBe toBeDefined toBeTruthy
toEqual toMatch toContain toThrow ...
Testing with Spies // Arrange const mySpy = vi.spyOn(service, 'getAllFood')
.mockReturnValue(...); // Act comp.updateFood(); // Assert expect(mySpy).toHaveBeenCalledTimes(1);
Testing Example - TestBed beforeEach(async () => { await TestBed.configureTestingModule({
imports: [HomeComponent], providers: [ { provide: FoodDataService, useClass: FoodServiceMock } ] }).compileComponents(); });
Testing Example - Async 1 it('should load todos', async ()
=> { 2 // arrange 3 const httpClient = TestBed.inject(HttpClient); 4 const service = TestBed.inject(TodoService); 5 const response = [ /* ...*/ ]; 6 const getSpy = vi .spyOn(httpClient, 'get') 7 8 .mockReturnValue(of(response)); 9 10 // act 11 const result = await lastValueFrom(service.loadTodos()); 12 13 // assert 14 expect(getSpy).toHaveBeenCalledOnce(); 15 expect(result).toEqual(response); 16 });
None
https://www.pluralsight.com/courses/angular-deep-dive-modern-state-signals-signal-store
Demo & Tasks Let's code!