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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Fabian Gosebrink
October 22, 2026
Technology
2
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
37
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
Active Record Connection Adaptersにおける長年の課題に再び取り組む
yahonda
0
280
その Valkey 使いこなしていますか?
onk
PRO
5
1.6k
「Docker Desktop不要の時代」は 来たのか?
ueponx
0
850
ストレスなくAIと付き合いたい!こんなときどうしてる?
namiki64
4
630
トークン化預金DCJPYの取り組みと活用ユースケース
finengine
0
180
Refining Active Record
shugo
0
170
Temporal 最高!でも改めて「日付」について調べたら人類の負債すぎる件
riyaamemiya
0
200
夫婦で子育てするための育児標準化
codmoninc
PRO
0
470
V8のArray.prototype.flatを最大約20倍速くするまでと、巨大OSSへの大規模コミットの道のり
riyaamemiya
0
310
[JAWS-UG彩の国埼玉#12]そろそろ準備する?re:Invent2026をやさしく解説 / reinvent2026-sainokuni
sh_fk2
1
360
自作バイナリを動かす「入口」8選
puhitaku
2
1.3k
hackers_champloo_2026_tidb
makocchi
0
170
Featured
See All Featured
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.5k
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
730
sira's awesome portfolio website redesign presentation
elsirapls
0
460
Testing 201, or: Great Expectations
jmmastey
46
8.3k
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
630
brightonSEO & MeasureFest 2025 - Winning Strategies for Black Friday CRO & PPC - Christian Goodrich
cargoodrich
3
870
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
430
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
270
Into the Great Unknown - MozCon
thekraken
41
2.8k
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
2
330
Ten Tips & Tricks for a 🌱 transition
stuffmc
1
270
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!