1
+ using Catalog . API . Controllers ;
2
+ using Catalog . Core . DTO ;
3
+ using Catalog . Core . Entities ;
4
+ using Catalog . Core . Repositories ;
5
+ using FluentValidation ;
6
+ using FluentValidation . Results ;
7
+ using Microsoft . AspNetCore . Mvc ;
8
+ using Microsoft . Extensions . Logging ;
9
+ using Moq ;
10
+
11
+ namespace Catalog . Test ;
12
+
13
+ public class ProductControllerTests
14
+ {
15
+ private readonly Mock < IProductRepository > _productRepositoryMock ;
16
+ private readonly Mock < ILogger < ProductController > > _loggerMock ;
17
+ private readonly Mock < IValidator < Product > > _validatorMock ;
18
+ private readonly ProductController _controller ;
19
+
20
+ public ProductControllerTests ( )
21
+ {
22
+ _productRepositoryMock = new Mock < IProductRepository > ( ) ;
23
+ _loggerMock = new Mock < ILogger < ProductController > > ( ) ;
24
+ _validatorMock = new Mock < IValidator < Product > > ( ) ;
25
+ _controller = new ProductController ( _productRepositoryMock . Object , _loggerMock . Object , _validatorMock . Object ) ;
26
+ }
27
+
28
+ [ Fact ]
29
+ public async Task Post_ValidProduct_ReturnsCreatedResult ( )
30
+ {
31
+ // Arrange
32
+ var productDtoRequest = new ProductDtoRequest
33
+ {
34
+ Name = "Test Product" ,
35
+ Description = "Test Description" ,
36
+ Price = 100 ,
37
+ Category = "Test Category" ,
38
+ Stock = 10 ,
39
+ Image = null
40
+ } ;
41
+
42
+ var product = new Product
43
+ {
44
+ Id = 1 ,
45
+ Name = productDtoRequest . Name ,
46
+ Description = productDtoRequest . Description ,
47
+ Price = productDtoRequest . Price ,
48
+ Category = productDtoRequest . Category ,
49
+ Stock = productDtoRequest . Stock
50
+ } ;
51
+
52
+ _validatorMock . Setup ( v => v . ValidateAsync ( It . IsAny < Product > ( ) , default ) )
53
+ . ReturnsAsync ( new ValidationResult ( ) ) ;
54
+
55
+ _productRepositoryMock . Setup ( repo => repo . CreateAsync ( It . IsAny < Product > ( ) ) )
56
+ . Returns ( Task . CompletedTask ) ;
57
+
58
+ // Act
59
+ var result = await _controller . Post ( productDtoRequest ) ;
60
+
61
+ // Assert
62
+ var createdResult = Assert . IsType < CreatedAtActionResult > ( result . Result ) ;
63
+ var returnValue = Assert . IsType < Product > ( createdResult . Value ) ;
64
+ Assert . Equal ( product . Name , returnValue . Name ) ;
65
+ _productRepositoryMock . Verify ( repo => repo . CreateAsync ( It . IsAny < Product > ( ) ) , Times . Once ) ;
66
+ }
67
+
68
+ [ Fact ]
69
+ public async Task Post_InvalidProduct_ReturnsBadRequest ( )
70
+ {
71
+ // Arrange
72
+ var productDtoRequest = new ProductDtoRequest
73
+ {
74
+ Name = "Test Product" ,
75
+ Description = "Test Description" ,
76
+ Price = 100 ,
77
+ Category = "Test Category" ,
78
+ Stock = 10 ,
79
+ Image = null
80
+ } ;
81
+
82
+ var validationFailures = new List < ValidationFailure >
83
+ {
84
+ new ValidationFailure ( "Name" , "Name is required" )
85
+ } ;
86
+
87
+ _validatorMock . Setup ( v => v . ValidateAsync ( It . IsAny < Product > ( ) , default ) )
88
+ . ReturnsAsync ( new ValidationResult ( validationFailures ) ) ;
89
+
90
+ // Act
91
+ var result = await _controller . Post ( productDtoRequest ) ;
92
+
93
+ // Assert
94
+ var badRequestResult = Assert . IsType < BadRequestObjectResult > ( result . Result ) ;
95
+ var problemDetails = Assert . IsType < ValidationProblemDetails > ( badRequestResult . Value ) ;
96
+ Assert . Contains ( "Name" , problemDetails . Errors ) ;
97
+ }
98
+
99
+ [ Fact ]
100
+ public async Task Get_ReturnsOkWithProducts ( )
101
+ {
102
+ // Arrange
103
+ var products = new List < Product >
104
+ {
105
+ new Product { Id = 1 , Name = "Product 1" } ,
106
+ new Product { Id = 2 , Name = "Product 2" }
107
+ } ;
108
+
109
+ _productRepositoryMock . Setup ( repo => repo . GetAllAsync ( ) )
110
+ . ReturnsAsync ( products ) ;
111
+
112
+ // Act
113
+ var result = await _controller . Get ( ) ;
114
+
115
+ // Assert
116
+ var okResult = Assert . IsType < OkObjectResult > ( result ) ;
117
+ var returnValue = Assert . IsType < List < ProductDtoResponse > > ( okResult . Value ) ;
118
+ Assert . Equal ( 2 , returnValue . Count ) ;
119
+ }
120
+
121
+ [ Fact ]
122
+ public async Task GetProduct_ExistingId_ReturnsOk ( )
123
+ {
124
+ // Arrange
125
+ var product = new Product { Id = 1 , Name = "Product 1" } ;
126
+
127
+ _productRepositoryMock . Setup ( repo => repo . GetByIdAsync ( 1 ) )
128
+ . ReturnsAsync ( product ) ;
129
+
130
+ // Act
131
+ var result = await _controller . GetProduct ( 1 ) ;
132
+
133
+ // Assert
134
+ var okResult = Assert . IsType < OkObjectResult > ( result . Result ) ;
135
+ var returnValue = Assert . IsType < ProductDtoResponse > ( okResult . Value ) ;
136
+ Assert . Equal ( product . Name , returnValue . Name ) ;
137
+ }
138
+
139
+ [ Fact ]
140
+ public async Task GetProduct_NonExistingId_ReturnsNotFound ( )
141
+ {
142
+ // Arrange
143
+ _productRepositoryMock . Setup ( repo => repo . GetByIdAsync ( 1 ) )
144
+ . ReturnsAsync ( ( Product ) null ! ) ;
145
+
146
+ // Act
147
+ var result = await _controller . GetProduct ( 1 ) ;
148
+
149
+ // Assert
150
+ Assert . IsType < NotFoundResult > ( result . Result ) ;
151
+ }
152
+
153
+ [ Fact ]
154
+ public async Task Put_ValidUpdate_ReturnsOk ( )
155
+ {
156
+ // Arrange
157
+ var product = new Product { Id = 1 , Name = "Product 1" , Price = 100 } ;
158
+ var updateDto = new ProductDtoUpdate { Name = "Updated Product" , Price = 150 } ;
159
+
160
+ _productRepositoryMock . Setup ( repo => repo . GetByIdAsync ( 1 ) )
161
+ . ReturnsAsync ( product ) ;
162
+
163
+ _productRepositoryMock . Setup ( repo => repo . UpdateAsync ( It . IsAny < Product > ( ) ) )
164
+ . Returns ( Task . CompletedTask ) ;
165
+
166
+ // Act
167
+ var result = await _controller . Put ( 1 , updateDto ) ;
168
+
169
+ // Assert
170
+ Assert . IsType < OkResult > ( result ) ;
171
+ _productRepositoryMock . Verify ( repo => repo . UpdateAsync ( It . IsAny < Product > ( ) ) , Times . Once ) ;
172
+ }
173
+
174
+ [ Fact ]
175
+ public async Task Delete_ExistingId_ReturnsOk ( )
176
+ {
177
+ // Arrange
178
+ var product = new Product { Id = 1 , Name = "Product 1" } ;
179
+
180
+ _productRepositoryMock . Setup ( repo => repo . GetByIdAsync ( 1 ) )
181
+ . ReturnsAsync ( product ) ;
182
+
183
+ _productRepositoryMock . Setup ( repo => repo . RemoveAsync ( 1 ) )
184
+ . Returns ( Task . CompletedTask ) ;
185
+
186
+ // Act
187
+ var result = await _controller . Delete ( 1 ) ;
188
+
189
+ // Assert
190
+ Assert . IsType < OkResult > ( result ) ;
191
+ _productRepositoryMock . Verify ( repo => repo . RemoveAsync ( 1 ) , Times . Once ) ;
192
+ }
193
+
194
+ [ Fact ]
195
+ public async Task Delete_NonExistingId_ReturnsNotFound ( )
196
+ {
197
+ // Arrange
198
+ _productRepositoryMock . Setup ( repo => repo . GetByIdAsync ( 1 ) )
199
+ . ReturnsAsync ( ( Product ) null ! ) ;
200
+
201
+ // Act
202
+ var result = await _controller . Delete ( 1 ) ;
203
+
204
+ // Assert
205
+ Assert . IsType < NotFoundResult > ( result ) ;
206
+ }
207
+ }
0 commit comments