Skip to content

Commit d78ae3a

Browse files
committed
Ex10 - moved unt testing to separate project in ContosoOnlineStore app.
1 parent 13f48f9 commit d78ae3a

File tree

5 files changed

+215
-256
lines changed

5 files changed

+215
-256
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFramework>net9.0</TargetFramework>
4+
<IsPackable>false</IsPackable>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
</PropertyGroup>
8+
<ItemGroup>
9+
<PackageReference Include="xunit" Version="2.4.2" />
10+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5" />
11+
<PackageReference Include="Moq" Version="4.20.69" />
12+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
13+
<PackageReference Include="coverlet.collector" Version="6.0.0" />
14+
</ItemGroup>
15+
<ItemGroup>
16+
<ProjectReference Include="..\ContosoOnlineStore\ContosoOnlineStore.csproj" />
17+
</ItemGroup>
18+
</Project>
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
using ContosoOnlineStore;
2+
using ContosoOnlineStore.Configuration;
3+
using ContosoOnlineStore.Services;
4+
using ContosoOnlineStore.Exceptions;
5+
using Microsoft.Extensions.Logging;
6+
using Microsoft.Extensions.Options;
7+
using Moq;
8+
9+
namespace ContosoOnlineStore.Tests;
10+
11+
public class ProductCatalogTests
12+
{
13+
private readonly IProductCatalog _catalog;
14+
private readonly Mock<ISecurityValidationService> _mockSecurity;
15+
private readonly Mock<ILogger<ProductCatalog>> _mockLogger;
16+
17+
public ProductCatalogTests()
18+
{
19+
_mockSecurity = new Mock<ISecurityValidationService>();
20+
_mockLogger = new Mock<ILogger<ProductCatalog>>();
21+
var appSettings = Options.Create(new AppSettings());
22+
23+
_catalog = new ProductCatalog(_mockSecurity.Object, _mockLogger.Object, appSettings);
24+
}
25+
26+
[Fact]
27+
public void GetProductById_ValidId_ReturnsProduct()
28+
{
29+
var productId = 1;
30+
var product = _catalog.GetProductById(productId);
31+
Assert.NotNull(product);
32+
Assert.Equal(productId, product.Id);
33+
}
34+
35+
[Fact]
36+
public void GetProductById_InvalidId_ReturnsNull()
37+
{
38+
var invalidId = 999;
39+
var product = _catalog.GetProductById(invalidId);
40+
Assert.Null(product);
41+
}
42+
43+
[Fact]
44+
public void GetAllProducts_ReturnsAllProducts()
45+
{
46+
var products = _catalog.GetAllProducts();
47+
Assert.NotEmpty(products);
48+
Assert.True(products.Count >= 20);
49+
}
50+
51+
[Fact]
52+
public void SearchProducts_ValidTerm_ReturnsMatchingProducts()
53+
{
54+
_mockSecurity.Setup(s => s.SanitizeInput(It.IsAny<string>())).Returns("phone");
55+
var results = _catalog.SearchProducts("phone");
56+
Assert.NotEmpty(results);
57+
Assert.All(results, p =>
58+
Assert.True(p.Name.ToLower().Contains("phone") ||
59+
p.Category.ToLower().Contains("phone") ||
60+
p.Description.ToLower().Contains("phone")));
61+
}
62+
}
63+
64+
public class OrderTests
65+
{
66+
[Fact]
67+
public void Constructor_ValidParameters_CreatesOrder()
68+
{
69+
var email = "[email protected]";
70+
var address = "123 Test St";
71+
var order = new Order(email, address);
72+
Assert.Equal(email, order.CustomerEmail);
73+
Assert.Equal(address, order.ShippingAddress);
74+
Assert.Equal(OrderStatus.Pending, order.Status);
75+
Assert.True(order.OrderId > 0);
76+
}
77+
78+
[Fact]
79+
public void AddItem_ValidItem_AddsToOrder()
80+
{
81+
var order = new Order();
82+
var item = new OrderItem(1, 2);
83+
order.AddItem(item);
84+
Assert.Contains(item, order.Items);
85+
var single = Assert.Single(order.Items);
86+
Assert.Equal(item.ProductId, single.ProductId);
87+
Assert.Equal(item.Quantity, single.Quantity);
88+
}
89+
90+
[Fact]
91+
public void AddItem_SameProduct_CombinesQuantity()
92+
{
93+
var order = new Order();
94+
var item1 = new OrderItem(1, 2);
95+
var item2 = new OrderItem(1, 3);
96+
order.AddItem(item1);
97+
order.AddItem(item2);
98+
var single = Assert.Single(order.Items);
99+
Assert.Equal(5, single.Quantity);
100+
Assert.Equal(1, single.ProductId);
101+
}
102+
}
103+
104+
public class SecurityValidationServiceTests
105+
{
106+
private readonly ISecurityValidationService _service;
107+
private readonly Mock<ILogger<SecurityValidationService>> _mockLogger;
108+
109+
public SecurityValidationServiceTests()
110+
{
111+
_mockLogger = new Mock<ILogger<SecurityValidationService>>();
112+
var appSettings = Options.Create(new AppSettings());
113+
_service = new SecurityValidationService(appSettings, _mockLogger.Object);
114+
}
115+
116+
[Fact]
117+
public void ValidateProduct_ValidProduct_DoesNotThrow()
118+
{
119+
var product = new Product(1, "Test Product", 10.99m, 100);
120+
var exception = Record.Exception(() => _service.ValidateProduct(product));
121+
Assert.Null(exception);
122+
}
123+
124+
[Fact]
125+
public void ValidateProduct_NullProduct_ThrowsArgumentNullException()
126+
{
127+
Assert.Throws<ArgumentNullException>(() => _service.ValidateProduct((Product)null!));
128+
}
129+
130+
[Theory]
131+
[InlineData("")]
132+
[InlineData(" ")]
133+
[InlineData(null)]
134+
public void ValidateProduct_InvalidName_ThrowsSecurityValidationException(string invalidName)
135+
{
136+
if (string.IsNullOrWhiteSpace(invalidName))
137+
{
138+
Assert.Throws<ArgumentException>(() => new Product(1, invalidName, 10.99m, 100));
139+
}
140+
}
141+
142+
[Fact]
143+
public void SanitizeInput_ValidInput_ReturnsSanitized()
144+
{
145+
var input = "Test<script>alert('xss')</script>";
146+
var result = _service.SanitizeInput(input);
147+
Assert.DoesNotContain("<", result);
148+
Assert.DoesNotContain(">", result);
149+
}
150+
}
151+
152+
public class InventoryManagerTests
153+
{
154+
private readonly Mock<IProductCatalog> _mockCatalog;
155+
private readonly Mock<ILogger<InventoryManager>> _mockLogger;
156+
private readonly IInventoryManager _inventoryManager;
157+
158+
public InventoryManagerTests()
159+
{
160+
_mockCatalog = new Mock<IProductCatalog>();
161+
_mockLogger = new Mock<ILogger<InventoryManager>>();
162+
var appSettings = Options.Create(new AppSettings());
163+
164+
var products = new List<Product>
165+
{
166+
new Product(1, "Product 1", 10.0m, 100),
167+
new Product(2, "Product 2", 20.0m, 50)
168+
};
169+
170+
_mockCatalog.Setup(c => c.GetAllProducts()).Returns(products);
171+
_inventoryManager = new InventoryManager(_mockCatalog.Object, _mockLogger.Object, appSettings);
172+
}
173+
174+
[Fact]
175+
public void GetStockLevel_ValidProductId_ReturnsStock()
176+
{
177+
var stock = _inventoryManager.GetStockLevel(1);
178+
Assert.Equal(100, stock);
179+
}
180+
181+
[Fact]
182+
public void IsInStock_SufficientStock_ReturnsTrue()
183+
{
184+
var inStock = _inventoryManager.IsInStock(1, 50);
185+
Assert.True(inStock);
186+
}
187+
188+
[Fact]
189+
public void IsInStock_InsufficientStock_ReturnsFalse()
190+
{
191+
var inStock = _inventoryManager.IsInStock(1, 150);
192+
Assert.False(inStock);
193+
}
194+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
global using Xunit;

DownloadableCodeProjects/standalone-lab-projects/implement-performance-profiling/ContosoOnlineStore/ContosoOnlineStore.csproj

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@
1414
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
1515
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
1616
<PackageReference Include="BenchmarkDotNet" Version="0.13.12" />
17-
<PackageReference Include="xunit" Version="2.4.2" />
18-
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5" />
19-
<PackageReference Include="Moq" Version="4.20.69" />
20-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
2117
</ItemGroup>
2218

2319
<ItemGroup>

0 commit comments

Comments
 (0)