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
6
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
Why State Is the Most Important Part of Your Angular Application
fabiangosebrink
0
45
Scalable Angular Architectures with Route-Based Architecture
fabiangosebrink
0
39
Advanced Signal Store: Structuring State for Real Angular Applications
fabiangosebrink
0
130
NgRx Signal Store - A Deeper Dive
fabiangosebrink
0
85
Modern Angular Apps in 2026
fabiangosebrink
0
150
Why State is the Most Important Part of Your Angular Application
fabiangosebrink
0
170
Angular testing made easy with Jest and Cypress
fabiangosebrink
0
190
Introducing state management into an application with NgRx
fabiangosebrink
0
280
Scalable architectures in Angular with Nx
fabiangosebrink
0
280
Other Decks in Technology
See All in Technology
ウォンテッドリーの最近のプロダクトと技術の紹介
stomk
0
220
Active Record Connection Adaptersにおける長年の課題に再び取り組む
yahonda
0
290
S3 Filesで挑む! 八戸せんべい汁の食べ頃問題
usanchuu
0
120
⾮構造化データを価値に変える AI エージェント基盤とその組織
ivry_presentationmaterials
0
200
Gemini Intelligence 入門 ― AppFunctions と Gemini Nano
takuroabe
0
310
LLM-as-a-Judgeは本当に信頼できるのか――評価器を評価する話
taka_aki
1
470
エンタメ企業のM&Aを支えるデータ基盤 ― 統合から店舗のリアルタイム分析まで / Data Engineering Summit 2026
genda
0
210
AI導入は済んだ。次は統制を作り替える番だ_AI×開発組織 Summit 2026
techtekt
PRO
0
390
OptunaHub: ブラックボックス最適化のためのプラットフォーム
pfn
PRO
0
140
宣言型部分更新は何を解決しどこへ向かうのか
shuta13
1
490
事業成長とデータ活用を止めないためのマネジメントへ挑戦
hiracky16
0
410
What Is JetBrains Air
x5gtrn
PRO
0
100
Featured
See All Featured
The Illustrated Children's Guide to Kubernetes
chrisshort
51
53k
Ethics towards AI in product and experience design
skipperchong
2
440
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.7k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
56
3.5k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
300
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
56k
Embracing the Ebb and Flow
colly
88
5.2k
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
290
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
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!