-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathwriting-tests.html
More file actions
459 lines (417 loc) · 24.2 KB
/
Copy pathwriting-tests.html
File metadata and controls
459 lines (417 loc) · 24.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Writing tests for Blazor components | bUnit </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Writing tests for Blazor components | bUnit ">
<meta name="description" content="bUnit is a unit testing library for Blazor Components. You can easily define components under test in C# or Razor syntax and verify outcome using semantic HTML diffing/comparison logic. You can interact with and inspect components, trigger event handlers, provide cascading values, inject services, mock IJsRuntime, and perform snapshot testing.">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" href="/favicon.ico">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
<link rel="manifest" href="/site.webmanifest">
<link rel="stylesheet" href="../../public/docfx.min.css">
<link rel="stylesheet" href="../../public/main.css">
<meta name="docfx:navrel" content="../../toc.html">
<meta name="docfx:tocrel" content="../toc.html">
<meta name="docfx:rel" content="../../">
<meta name="docfx:docurl" content="https://github.com/bUnit-dev/bUnit/blob/stable/docs/site/docs/getting-started/writing-tests.md/#L1">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for "{query}"">
<meta name="loc:searchNoResults" content="No results for "{query}"">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
</head>
<script type="module" src="./../../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../../index.html">
<img id="logo" class="svg" src="../..//images/bunit-logo.png" alt="bUnit">
bUnit
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled="" placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" style="margin-top: -.65em; margin-left: -.8em" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="writing-tests">
<h1 id="writing-tests-for-blazor-components">Writing tests for Blazor components</h1>
<p>Testing Blazor components is a little different from testing regular C# classes: Blazor components are <em>rendered</em>, they have the <em>Blazor component life cycle</em> during which we can <em>provide input</em> to them, and they can <em>produce output</em>.</p>
<p>Use <strong>bUnit</strong> to render the component under test, pass in its parameters, inject required services, and access the rendered component instance and the markup it has produced.</p>
<p>Rendering a component happens through bUnit's <a class="xref" href="../../api/Bunit.BunitContext.html">BunitContext</a>. The result of the rendering is an <code>RenderedComponent</code>, referred to as a "rendered component", that provides access to the component instance and the markup produced by the component.</p>
<h2 id="write-tests-in-cs-or-razor-files">Write tests in <code>.cs</code> or <code>.razor</code> files</h2>
<p>bUnit works with MSTest, NUnit, and xUnit, and it allows you to write the unit tests in either <code>.cs</code> or <code>.razor</code> files.</p>
<p>The latter, writing tests in <code>.razor</code> files, provides an easier way to declare component markup and HTML markup in the tests, so it will most likely be the go-to for many people in the future.</p>
<p><em>However</em>, the current Razor editor in Visual Studio 2022 does not offer all the code editing features available in the C# editor, so that is something to consider if you choose to write tests in <code>.razor</code> files.</p>
<p>The following sections show how to get started writing tests in either <code>.cs</code> or <code>.razor</code> files.</p>
<h2 id="creating-basic-tests-in-razor-files">Creating basic tests in <code>.razor</code> files</h2>
<p>Before writing tests in <code>.razor</code> files, a few things needs to be in place:</p>
<ol>
<li><p>Make sure the test project has the SDK type set to <code>Microsoft.NET.Sdk.Razor</code>. Otherwise the Blazor compiler will not translate your <code>.razor</code> files into runnable code.</p>
</li>
<li><p>Add an <code>_Imports.razor</code> file to the test project. It serves the same purpose as <code>_Imports.razor</code> files in regular Blazor projects. These using statements are useful to add right away:</p>
<pre><code class="lang-cshtml">@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop
@using Microsoft.Extensions.DependencyInjection
@using AngleSharp.Dom
@using Bunit
@using Bunit.TestDoubles
</code></pre>
</li>
</ol>
<p>Also add an using statement for your general purpose testing framework, e.g. <code>@using Xunit</code> for xUnit.</p>
<p>With that in place, lets look at a simple example that tests the following <code><HelloWorld></code> component:</p>
<pre><code class="lang-cshtml" name="HelloWorld.razor"><h1>Hello world from Blazor</h1>
</code></pre><div class="tabGroup" id="tabgroup_1">
<ul role="tablist">
<li role="presentation">
<a href="#tabpanel_1_xunit" role="tab" aria-controls="tabpanel_1_xunit" data-tab="xunit" tabindex="0" aria-selected="true">xUnit</a>
</li>
<li role="presentation">
<a href="#tabpanel_1_nunit" role="tab" aria-controls="tabpanel_1_nunit" data-tab="nunit" tabindex="-1">NUnit</a>
</li>
<li role="presentation">
<a href="#tabpanel_1_mstest" role="tab" aria-controls="tabpanel_1_mstest" data-tab="mstest" tabindex="-1">MSTest</a>
</li>
</ul>
<section id="tabpanel_1_xunit" role="tabpanel" data-tab="xunit">
<pre><code class="lang-cshtml" name="HelloWorldRazorTest.razor">@inherits BunitContext
@code
{
[Fact]
public void HelloWorldComponentRendersCorrectly()
{
// Act
var cut = Render(@<HelloWorld/>);
// Assert
cut.MarkupMatches(@<h1>Hello world from Blazor</h1>);
}
}
</code></pre>
<p>The test above does the following:</p>
<ol>
<li>Inherits from the bUnit <a class="xref" href="../../api/Bunit.BunitContext.html">BunitContext</a>. This base class offers the majority of functions.</li>
<li>Renders the <code><HelloWorld></code> component using <a class="xref" href="../../api/Bunit.BunitContext.html">BunitContext</a>, which is done through the <code>Render(RenderFragment)</code> method. We cover passing parameters to components on the <a class="xref" href="../providing-input/passing-parameters-to-components.html">Passing parameters to components</a> page.</li>
<li>Verifies the rendered markup from the <code><HelloWorld></code> component using the <code>MarkupMatches</code> method. The <code>MarkupMatches</code> method performs a semantic comparison of the expected markup with the rendered markup.</li>
</ol>
</section>
<section id="tabpanel_1_nunit" role="tabpanel" data-tab="nunit" aria-hidden="true" hidden="hidden">
<pre><code class="lang-cshtml" name="HelloWorldRazorTest.razor">@inherits BunitContext
@code
{
[Test]
public void HelloWorldComponentRendersCorrectly()
{
// Act
var cut = Render(@<HelloWorld />);
// Assert
cut.MarkupMatches(@<h1>Hello world from Blazor</h1>);
}
}
</code></pre>
<p>Use the <a href="https://docs.nunit.org/articles/nunit/writing-tests/attributes/fixturelifecycle.html">LifeCycle.InstancePerTestCase</a> attribute (introduced in NUnit 3.13) so that a new instance of the test class is created for each test removing the need for the wrapper.</p>
<pre><code class="lang-csharp" name="HelloWorldInstancePerTestCase.cs">[FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
public class HelloWorldInstancePerTestCase : Bunit.BunitContext
{
[Test]
public void HelloWorldComponentRendersCorrectly()
{
// Act
var cut = Render<HelloWorld>();
// Assert
cut.MarkupMatches("<h1>Hello world from Blazor</h1>");
}
}
</code></pre></section>
<section id="tabpanel_1_mstest" role="tabpanel" data-tab="mstest" aria-hidden="true" hidden="hidden">
<pre><code class="lang-cshtml" name="HelloWorldRazorTest.razor">@attribute [TestClass]
@inherits BunitContext
@code
{
[TestMethod]
public void HelloWorldComponentRendersCorrectly()
{
// Act
var cut = Render(@<HelloWorld/>);
// Assert
cut.MarkupMatches(@<h1>Hello world from Blazor</h1>);
}
}
</code></pre></section>
</div>
<div class="TIP">
<h5>Tip</h5>
<p>Learn more about how the semantic HTML/markup comparison in bUnit works, and how to customize it, on the <a class="xref" href="../verification/semantic-html-comparison.html">Customizing the semantic HTML comparison</a> page.</p>
</div>
<div class="TIP">
<h5>Tip</h5>
<p>In bUnit tests, we like to use the abbreviation <code>CUT</code>, short for "component under test", to indicate the component that is being tested. This is inspired by the common testing abbreviation <code>SUT</code>, short for "system under test".</p>
</div>
<h3 id="secret-sauce-of-razor-files-tests">Secret sauce of '.razor' files tests</h3>
<p>The trick employed in these tests is the "<a href="https://docs.microsoft.com/en-us/aspnet/core/blazor/components/?view=aspnetcore-5.0#razor-templates">inline Razor templates syntax</a>", i.e. where a render fragment is simply created using the <code>@<{HTML tag}>...</{HTML tag}></code> notation. In that notation there is no need to do any escaping of e.g. the quotation mark (<code>"</code>), that is usually associated with working with markup in C# code.</p>
<p>One small caveat to be aware of is that the inline Razor templates syntax only supports one outer element, e.g. this is OK:</p>
<pre><code class="lang-cshtml">@<Foo>
<Bar>
<Baz>...</Baz>
</Bar>
</Foo>
</code></pre>
<p>However, this will <strong>not</strong> work:</p>
<pre><code class="lang-cshtml">@<Foo></Foo>
<Bar></Bar>
</code></pre>
<p>There is a simple workaround though: wrap all elements in the special Blazor element <code><text></code>. The <code><text></code> element will not be part of the rendered output, but it provides a simple way to group multiple root elements into a single inline Razor template. E.g.:</p>
<pre><code class="lang-cshtml">@<text>
<Foo></Foo>
<Bar></Bar>
</text>
</code></pre>
<h2 id="creating-basic-tests-in-cs-files">Creating basic tests in <code>.cs</code> files</h2>
<p>This is a simple example of writing tests in <code>.cs</code> files which tests the following <code><HelloWorld></code> component:</p>
<pre><code class="lang-cshtml" name="HelloWorld.razor"><h1>Hello world from Blazor</h1>
</code></pre><div class="tabGroup" id="tabgroup_2">
<ul role="tablist">
<li role="presentation">
<a href="#tabpanel_2_xunit" role="tab" aria-controls="tabpanel_2_xunit" data-tab="xunit" tabindex="0" aria-selected="true">xUnit</a>
</li>
<li role="presentation">
<a href="#tabpanel_2_nunit" role="tab" aria-controls="tabpanel_2_nunit" data-tab="nunit" tabindex="-1">NUnit</a>
</li>
<li role="presentation">
<a href="#tabpanel_2_mstest" role="tab" aria-controls="tabpanel_2_mstest" data-tab="mstest" tabindex="-1">MSTest</a>
</li>
</ul>
<section id="tabpanel_2_xunit" role="tabpanel" data-tab="xunit">
<pre><code class="lang-csharp" name="HelloWorldTest.cs">using Xunit;
using Bunit;
public class HelloWorldTest : BunitContext
{
[Fact]
public void HelloWorldComponentRendersCorrectly()
{
// Act
var cut = Render<HelloWorld>();
// Assert
cut.MarkupMatches("<h1>Hello world from Blazor</h1>");
}
}
</code></pre>
<p>The test above does the following:</p>
<ol>
<li>Inherits from the bUnit's <code>BunitContext</code>. This base class offers the majority of functions.</li>
<li>Renders the <code><HelloWorld></code> component using <a class="xref" href="../../api/Bunit.BunitContext.html">BunitContext</a>, which is done through the <a class="xref" href="../../api/Bunit.BunitContext.html#Bunit_BunitContext_Render__1_System_Action_Bunit_ComponentParameterCollectionBuilder___0___">Render<TComponent>(Action<ComponentParameterCollectionBuilder<TComponent>>?)</a> method. We cover passing parameters to components on the <a class="xref" href="../providing-input/passing-parameters-to-components.html">Passing parameters to components</a> page.</li>
<li>Verifies the rendered markup from the <code><HelloWorld></code> component using the <code>MarkupMatches</code> method. The <code>MarkupMatches</code> method performs a semantic comparison of the expected markup with the rendered markup.</li>
</ol>
</section>
<section id="tabpanel_2_nunit" role="tabpanel" data-tab="nunit" aria-hidden="true" hidden="hidden">
<pre><code class="lang-csharp" name="HelloWorldTest.cs">using Bunit;
using NUnit.Framework;
public class HelloWorldTest : BunitContext
{
[Test]
public void HelloWorldComponentRendersCorrectly()
{
// Act
var cut = Render<HelloWorld>();
// Assert
cut.MarkupMatches("<h1>Hello world from Blazor</h1>");
}
}
</code></pre>
<p>The test above does the following:</p>
<ol>
<li>Inherits from the <code>BunitContext</code> listed above. This base class offers the majority of functions.</li>
<li>Renders the <code><HelloWorld></code> component using <a class="xref" href="../../api/Bunit.BunitContext.html">BunitContext</a>, which is done through the <a class="xref" href="../../api/Bunit.BunitContext.html#Bunit_BunitContext_Render__1_System_Action_Bunit_ComponentParameterCollectionBuilder___0___">Render<TComponent>(Action<ComponentParameterCollectionBuilder<TComponent>>?)</a> method. We cover passing parameters to components on the <a class="xref" href="../providing-input/passing-parameters-to-components.html">Passing parameters to components</a> page.</li>
<li>Verifies the rendered markup from the <code><HelloWorld></code> component using the <code>MarkupMatches</code> method. The <code>MarkupMatches</code> method performs a semantic comparison of the expected markup with the rendered markup.</li>
</ol>
<p>Alternatively, use the <a href="https://docs.nunit.org/articles/nunit/writing-tests/attributes/fixturelifecycle.html">LifeCycle.InstancePerTestCase</a> attribute (introduced in NUnit 3.13) so that a new instance of the test class is created for each test removing the need for the wrapper.</p>
<pre><code class="lang-csharp" name="HelloWorldRazorInstancePerTestCase.razor">using NUnit.Framework;
namespace Bunit.Docs.Samples;
[FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
public class HelloWorldInstancePerTestCase : Bunit.BunitContext
{
[Test]
public void HelloWorldComponentRendersCorrectly()
{
// Act
var cut = Render<HelloWorld>();
// Assert
cut.MarkupMatches("<h1>Hello world from Blazor</h1>");
}
}
</code></pre></section>
<section id="tabpanel_2_mstest" role="tabpanel" data-tab="mstest" aria-hidden="true" hidden="hidden">
<pre><code class="lang-csharp" name="HelloWorldTest.cs">using Microsoft.VisualStudio.TestTools.UnitTesting;
using Bunit;
[TestClass]
public class HelloWorldTest : BunitContext
{
[TestMethod]
public void HelloWorldComponentRendersCorrectly()
{
// Act
var cut = Render<HelloWorld>();
// Assert
cut.MarkupMatches("<h1>Hello world from Blazor</h1>");
}
}
</code></pre>
<p>The test above does the following:</p>
<ol>
<li>Inherits from the <code>BunitContext</code> listed above. This base class offers the majority of functions.</li>
<li>Renders the <code><HelloWorld></code> component using <a class="xref" href="../../api/Bunit.BunitContext.html">BunitContext</a>, which is done through the <a class="xref" href="../../api/Bunit.BunitContext.html#Bunit_BunitContext_Render__1_System_Action_Bunit_ComponentParameterCollectionBuilder___0___">Render<TComponent>(Action<ComponentParameterCollectionBuilder<TComponent>>?)</a> method. We cover passing parameters to components on the <a class="xref" href="../providing-input/passing-parameters-to-components.html">Passing parameters to components</a> page.</li>
<li>Verifies the rendered markup from the <code><HelloWorld></code> component using the <code>MarkupMatches</code> method. The <code>MarkupMatches</code> method performs a semantic comparison of the expected markup with the rendered markup.</li>
</ol>
</section>
</div>
<div class="TIP">
<h5>Tip</h5>
<p>Learn more about how the semantic HTML/markup comparison in bUnit works, and how to customize it, on the <a class="xref" href="../verification/semantic-html-comparison.html">Customizing the semantic HTML comparison</a> page.</p>
</div>
<div class="TIP">
<h5>Tip</h5>
<p>In bUnit tests, we like to use the abbreviation <code>CUT</code>, short for "component under test", to indicate the component that is being tested. This is inspired by the common testing abbreviation <code>SUT</code>, short for "system under test".</p>
</div>
<h3 id="instantiate-bunitcontext-in-each-test">Instantiate BunitContext in each test</h3>
<p>If you prefer to instantiate <a class="xref" href="../../api/Bunit.BunitContext.html">BunitContext</a> in each test, instead of inheriting from it, you can do so. This can be useful if you have your own base class that you want to inherit from, or if you want to use a different test framework than the ones listed here.</p>
<p>Just be aware that all examples in the rest of the documentation assumes that you are inheriting from <a class="xref" href="../../api/Bunit.BunitContext.html">BunitContext</a>, so adjust accordingly.</p>
<div class="tabGroup" id="tabgroup_3">
<ul role="tablist">
<li role="presentation">
<a href="#tabpanel_3_xunit" role="tab" aria-controls="tabpanel_3_xunit" data-tab="xunit" tabindex="0" aria-selected="true">xUnit</a>
</li>
<li role="presentation">
<a href="#tabpanel_3_nunit" role="tab" aria-controls="tabpanel_3_nunit" data-tab="nunit" tabindex="-1">NUnit</a>
</li>
<li role="presentation">
<a href="#tabpanel_3_mstest" role="tab" aria-controls="tabpanel_3_mstest" data-tab="mstest" tabindex="-1">MSTest</a>
</li>
</ul>
<section id="tabpanel_3_xunit" role="tabpanel" data-tab="xunit">
<pre><code class="lang-csharp" name="HelloWorldExplicitContextTest.cs">public class HelloWorldExplicitContext
{
[Fact]
public void HelloWorldComponentRendersCorrectly()
{
// Arrange
using var ctx = new BunitContext();
// Act
var cut = ctx.Render<HelloWorld>();
// Assert
cut.MarkupMatches("<h1>Hello world from Blazor</h1>");
}
}
</code></pre></section>
<section id="tabpanel_3_nunit" role="tabpanel" data-tab="nunit" aria-hidden="true" hidden="hidden">
<pre><code class="lang-csharp" name="HelloWorldExplicitContextTest.cs">public class HelloWorldExplicitContext
{
[Test]
public void HelloWorldComponentRendersCorrectly()
{
// Arrange
using var ctx = new Bunit.BunitContext();
// Act
var cut = ctx.Render<HelloWorld>();
// Assert
cut.MarkupMatches("<h1>Hello world from Blazor</h1>");
}
}
</code></pre></section>
<section id="tabpanel_3_mstest" role="tabpanel" data-tab="mstest" aria-hidden="true" hidden="hidden">
<pre><code class="lang-csharp" name="HelloWorldImplicitContextTest.cs">[TestClass]
public class HelloWorldExplicitContext
{
[TestMethod]
public void HelloWorldComponentRendersCorrectly()
{
// Arrange
using var ctx = new Bunit.BunitContext();
// Act
var cut = ctx.Render<HelloWorld>();
// Assert
cut.MarkupMatches("<h1>Hello world from Blazor</h1>");
}
}
</code></pre><h2 id="further-reading">Further reading</h2>
<p>With the basics out of the way, next we will look at how to pass parameters and inject services into our component under test. After that, we will cover the ways in which we can verify the outcome of a rendering in more detail</p>
<ul>
<li><a class="xref" href="../providing-input/passing-parameters-to-components.html">Passing parameters to components</a></li>
<li><a class="xref" href="../providing-input/inject-services-into-components.html">Injecting services into components under test</a></li>
<li><a class="xref" href="../verification/verify-markup.html">Verifying markup from a component</a></li>
<li><a class="xref" href="../verification/verify-component-state.html">Verifying the state of a component under test</a></li>
<li><a class="xref" href="../interaction/trigger-event-handlers.html">Triggering event handlers in components</a></li>
</ul>
</section>
</div>
</article>
<div class="contribution d-print-none">
<a href="https://github.com/bUnit-dev/bUnit/blob/stable/docs/site/docs/getting-started/writing-tests.md/#L1" class="edit-link">Edit this page</a>
</div>
<div class="next-article d-print-none border-top" id="nextArticle"></div>
</div>
<div class="affix">
<nav id="affix"></nav>
<div class="border-top text-center pt-4">
<a class="d-block" href="https://dotnetfoundation.org" title=".NET Foundation">
<img width="150" src="/sponsors/dotnetfoundation_v4_purple.svg" alt=".NET Foundation">
</a>
<p class="pt-1"><small>Supported by the <a href="https://dotnetfoundation.org">.NET Foundation</a>.</small></p>
</div>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary bg-body-tertiary">
<div class="container-xxl">
<div class="flex-fill">
<small>Documentation updated on 2026-08-10T12:54:03.0000000+00:00 in commit d4d81d9e5b</small>
</div>
</div>
</footer>
</body>
</html>