Free AI web copilot to create summaries, insights and extended knowledge, download it at here
8645
Abstract
<span class="hljs-keyword">async</span> <span class="hljs-title function_">delete</span>(<span class="hljs-attr">id</span>: <span class="hljs-built_in">string</span>): <span class="hljs-title class_">Promise</span><<span class="hljs-title class_">Item</span>> {
<span class="hljs-keyword">const</span> item = <span class="hljs-keyword">await</span> <span class="hljs-variable language_">this</span>.<span class="hljs-property">itemModel</span>.<span class="hljs-title function_">findByIdAndRemove</span>(id);
<span class="hljs-keyword">if</span> (!item) {
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">NotFoundException</span>(<span class="hljs-string">'Item not found'</span>);
}
<span class="hljs-keyword">return</span> item;
}
}</pre></div><p id="61ef">3. Controller with Validation:</p><p id="425a">Inside <code>item.controller.ts</code>:</p><div id="dace"><pre><span class="hljs-keyword">import</span> { Body, Controller, Get, Post, Put, Delete, Param, NotFoundException, BadRequestException, ParseUUIDPipe } from <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span> { CreateItemDto } from <span class="hljs-string">'./create-item.dto'</span>;
<span class="hljs-keyword">import</span> { UpdateItemDto } from <span class="hljs-string">'./update-item.dto'</span>;
<span class="hljs-keyword">import</span> { ItemService } from <span class="hljs-string">'./item.service'</span>;
<span class="hljs-keyword">import</span> { Item } from <span class="hljs-string">'./item.schema'</span>;
<span class="hljs-meta">@Controller(<span class="hljs-string">'items'</span>)</span>
export <span class="hljs-keyword">class</span> <span class="hljs-title class_">ItemController</span> {
<span class="hljs-keyword">constructor</span>(<span class="hljs-keyword">private</span> readonly itemService: ItemService) { }
<span class="hljs-meta">@Post()</span>
async create(<span class="hljs-meta">@Body()</span> createItemDto: CreateItemDto): Promise<Item> {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.itemService.create(createItemDto);
}
<span class="hljs-meta">@Get()</span>
async findAll(): Promise<Item[]> {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.itemService.findAll();
}
<span class="hljs-meta">@Get(<span class="hljs-string">':id'</span>)</span>
async findOne(<span class="hljs-meta">@Param(<span class="hljs-string">'id'</span>)</span> id: string): Promise<Item> {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.itemService.findOne(id);
}
<span class="hljs-meta">@Put(<span class="hljs-string">':id'</span>)</span>
async update(<span class="hljs-meta">@Param(<span class="hljs-string">'id'</span>)</span> id: string, <span class="hljs-meta">@Body()</span> updateItemDto: UpdateItemDto): Promise<Item> {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.itemService.update(id, updateItemDto);
}
<span class="hljs-meta">@Delete(<span class="hljs-string">':id'</span>)</span>
async delete(<span class="hljs-meta">@Param(<span class="hljs-string">'id'</span>)</span> id: string): Promise<Item> {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.itemService.delete(id);
}
}</pre></div><p id="7771">4. Activate auto-validation:</p><p id="61fc">update the fille main.ts</p><div id="fe08"><pre><span class="hljs-keyword">import</span> { <span class="hljs-title class_">NestFactory</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/core'</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title class_">AppModule</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'./app.module'</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title class_">ValidationPipe</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">bootstrap</span>(<span class="hljs-params"></span>) {
<span class="hljs-keyword">const</span> app = <span class="hljs-keyword">await</span> <span class="hljs-title class_">NestFactory</span>.<span class="hljs-title function_">create</span>(<span class="hljs-title class_">AppModule</span>);
app.<span class="hljs-title function_">useGlobalPipes</span>(<span class="hljs-keyword">new</span> <span class="hljs-title class_">ValidationPipe</span>());
<span class="hljs-keyword">await</span> app.<span class="hljs-title function_">listen</span>(<span class="hljs-number">3000</span>);
}
<span class="hljs-title function_">bootstrap</span>();</pre></div><h1 id="a2cc">Unit Testing:</h1><p id="0fac">1. Setup:</p><p id="23ed">Install required packages:</p><div id="89f0"><pre>npm install @nestjs/testing</pre></div><p id="2a92">2. Testing the Service:</p><p id="bc15">In the <code>item.service.spec.ts</code>:</p><div id="b87f"><pre><span class="hljs-keyword">import</span> { Test, TestingModule } from <span class="hljs-string">'@nestjs/testing'</span>;
<span class="hljs-keyword">import</span> { ItemService } from <span class="hljs-string">'./item.service'</span>;
<span class="hljs-keyword">import</span> { getModelToken } from <span class="hljs-string">'@nestjs/mongoose'</span>;
<span class="hljs-keyword">import</span> { NotFoundException } from <span class="hljs-string">'@nestjs/common'</span>;
describe(<span class="hljs-string">'ItemService'</span>, () => {
let service: ItemService;
let mockItemModel;
beforeEach(<span class="hljs-keyword">async</span> () => {
mockItemModel = {
find: jest.fn(),
findById: jest.fn(),
findByIdAndUpdate: jest.fn(),
findByIdAndRemove: jest.fn(),
create: jest.fn(),
};
<span class="hljs-keyword">const</span> module: TestingModule = <span class="hljs-keyword">await</span> Test.createTestingModule({
providers: [
ItemService,
{
provide: getModelToken(<span class="hljs-string">'Item'</span>),
useValue: mockItemModel,
},
],
}).compile();
service = module.<span class="hljs-keyword">get</span><ItemService>(ItemService);
});
it(<span class="hljs-string">'should be defined'</span>, () => {
expect(service).toBeDefined();
});
describe(<span class="hljs-string">'findAll'</span>, () => {
it(<span class="hljs-string">'should return an array of items'</span>, <span class="hljs-keyword">async</span> () => {
<span class="hljs-keyword">const</span> result = [];
mockItemModel.find.mockResolvedValue(result);
expect(<span class="hljs-keyword">await</span> service.findAll()).toBe(result);
});
});
describe(<span class="hljs-string">'findOne'</span>, () => {
it(<span class="hljs-string">'should retrieve an item by its ID'</span>, <span class="hljs-keyword">async</span> () => {
<span class="hljs-keyword">const</span> result = { _id: <span class="hljs-string">'some-id'</span>, name: <span class="hljs-string">'ItemName'</span> };
mockItemModel.findById.mockResolvedValue(result);
expect(<span class="hljs-keyword">await</span> service.findOne(<span class="hljs-string">'some-id'</span>)).toBe(result);
});
it(<span class="hljs-string">'should throw NotFoundException when item does not exist'</span>, <span class="hljs-keyword">async</span> () => {
mockItemModel.findById.mockResolvedValue(<span class="hljs-keyword">null</span>);
<span class="hljs-keyword">await</span> expect(service.findOne(<span class="hljs-string">'some-id'</span>)).rejects.toThrow(NotFoundException);
});
});
describe(<span class="hljs-string">'create'</span>, () => {
it(<span class="hljs-string">'should successfully insert an item'</span>, <span class="hljs-keyword">async</span> () => {
<span class="hljs-keyword">const</span> createItemDto = { name: <span class="hljs-string">'NewItem'</span> };
mockItemModel.create.mockResolvedValue(createItemDto);
expect(<span class="hljs-keyword">await</span> service.create(createItemDto)).toBe(createItemDto);
});
});
describe(<span class="hljs-string">'update'</span>, () => {
it(<span class="hljs-string">'should update an item'</span>, <span class="hljs-keyword">async</span> () =&
Options
gt; {
<span class="hljs-keyword">const</span> result = { _id: <span class="hljs-string">'some-id'</span>, name: <span class="hljs-string">'UpdatedName'</span> };
<span class="hljs-keyword">const</span> updateItemDto = { name: <span class="hljs-string">'UpdatedName'</span> };
mockItemModel.findByIdAndUpdate.mockResolvedValue(result);
expect(<span class="hljs-keyword">await</span> service.update(<span class="hljs-string">'some-id'</span>, updateItemDto)).toBe(result);
});
it(<span class="hljs-string">'should throw NotFoundException when item does not exist'</span>, <span class="hljs-keyword">async</span> () => {
mockItemModel.findByIdAndUpdate.mockResolvedValue(<span class="hljs-keyword">null</span>);
<span class="hljs-keyword">await</span> expect(service.update(<span class="hljs-string">'some-id'</span>, {})).rejects.toThrow(NotFoundException);
});
});
describe(<span class="hljs-string">'delete'</span>, () => {
it(<span class="hljs-string">'should delete an item by its ID'</span>, <span class="hljs-keyword">async</span> () => {
<span class="hljs-keyword">const</span> result = { _id: <span class="hljs-string">'some-id'</span>, name: <span class="hljs-string">'ItemToDelete'</span> };
mockItemModel.findByIdAndRemove.mockResolvedValue(result);
expect(<span class="hljs-keyword">await</span> service.delete(<span class="hljs-string">'some-id'</span>)).toBe(result);
});
it(<span class="hljs-string">'should throw NotFoundException when item does not exist'</span>, <span class="hljs-keyword">async</span> () => {
mockItemModel.findByIdAndRemove.mockResolvedValue(<span class="hljs-keyword">null</span>);
<span class="hljs-keyword">await</span> expect(service.delete(<span class="hljs-string">'some-id'</span>)).rejects.toThrow(NotFoundException);
});
});
});</pre></div><h1 id="ceb6">E2E Testing:</h1><p id="33a2">Testing the Service:</p><p id="4f53">create new file <code>item.e2e-spec.ts</code>:</p><div id="6d4c"><pre><span class="hljs-keyword">import</span> { <span class="hljs-title class_">Test</span>, <span class="hljs-title class_">TestingModule</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/testing'</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title class_">INestApplication</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> request <span class="hljs-keyword">from</span> <span class="hljs-string">'supertest'</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title class_">AppModule</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'./../src/app.module'</span>;
<span class="hljs-title function_">describe</span>(<span class="hljs-string">'ItemController (e2e)'</span>, <span class="hljs-function">() =></span> {
<span class="hljs-keyword">let</span> <span class="hljs-attr">app</span>: <span class="hljs-title class_">INestApplication</span>;
<span class="hljs-title function_">beforeAll</span>(<span class="hljs-keyword">async</span> () => {
<span class="hljs-keyword">const</span> <span class="hljs-attr">moduleFixture</span>: <span class="hljs-title class_">TestingModule</span> = <span class="hljs-keyword">await</span> <span class="hljs-title class_">Test</span>.<span class="hljs-title function_">createTestingModule</span>({
<span class="hljs-attr">imports</span>: [<span class="hljs-title class_">AppModule</span>],
}).<span class="hljs-title function_">compile</span>();
app = moduleFixture.<span class="hljs-title function_">createNestApplication</span>();
<span class="hljs-keyword">await</span> app.<span class="hljs-title function_">init</span>();
});
<span class="hljs-title function_">afterAll</span>(<span class="hljs-keyword">async</span> () => {
<span class="hljs-keyword">await</span> app.<span class="hljs-title function_">close</span>();
});
<span class="hljs-title function_">it</span>(<span class="hljs-string">'/items (GET)'</span>, <span class="hljs-function">() =></span> {
<span class="hljs-keyword">return</span> <span class="hljs-title function_">request</span>(app.<span class="hljs-title function_">getHttpServer</span>())
.<span class="hljs-title function_">get</span>(<span class="hljs-string">'/items'</span>)
.<span class="hljs-title function_">expect</span>(<span class="hljs-number">200</span>);
});
<span class="hljs-keyword">let</span> <span class="hljs-attr">itemId</span>: <span class="hljs-built_in">string</span>;
<span class="hljs-title function_">it</span>(<span class="hljs-string">'/items (POST)'</span>, <span class="hljs-function">() =></span> {
<span class="hljs-keyword">return</span> <span class="hljs-title function_">request</span>(app.<span class="hljs-title function_">getHttpServer</span>())
.<span class="hljs-title function_">post</span>(<span class="hljs-string">'/items'</span>)
.<span class="hljs-title function_">send</span>({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Sample Item'</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">'Sample Description'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">100</span> })
.<span class="hljs-title function_">expect</span>(<span class="hljs-number">201</span>)
.<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">response</span> =></span> {
itemId = response.<span class="hljs-property">body</span>.<span class="hljs-property">_id</span>; <span class="hljs-comment">// Assuming the response contains the created item with its ID</span>
});
});
<span class="hljs-title function_">it</span>(<span class="hljs-string">'/items/:id (GET)'</span>, <span class="hljs-function">() =></span> {
<span class="hljs-keyword">return</span> <span class="hljs-title function_">request</span>(app.<span class="hljs-title function_">getHttpServer</span>())
.<span class="hljs-title function_">get</span>(<span class="hljs-string">`/items/<span class="hljs-subst">${itemId}</span>`</span>)
.<span class="hljs-title function_">expect</span>(<span class="hljs-number">200</span>)
.<span class="hljs-title function_">expect</span>(<span class="hljs-function"><span class="hljs-params">response</span> =></span> {
<span class="hljs-title function_">expect</span>(response.<span class="hljs-property">body</span>.<span class="hljs-property">name</span>).<span class="hljs-title function_">toEqual</span>(<span class="hljs-string">'Sample Item'</span>);
});
});
<span class="hljs-title function_">it</span>(<span class="hljs-string">'/items/:id (PUT)'</span>, <span class="hljs-function">() =></span> {
<span class="hljs-keyword">return</span> <span class="hljs-title function_">request</span>(app.<span class="hljs-title function_">getHttpServer</span>())
.<span class="hljs-title function_">put</span>(<span class="hljs-string">`/items/<span class="hljs-subst">${itemId}</span>`</span>)
.<span class="hljs-title function_">send</span>({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Updated Item'</span> })
.<span class="hljs-title function_">expect</span>(<span class="hljs-number">200</span>);
});
<span class="hljs-title function_">it</span>(<span class="hljs-string">'/items/:id (DELETE)'</span>, <span class="hljs-function">() =></span> {
<span class="hljs-keyword">return</span> <span class="hljs-title function_">request</span>(app.<span class="hljs-title function_">getHttpServer</span>())
.<span class="hljs-title function_">delete</span>(<span class="hljs-string">`/items/<span class="hljs-subst">${itemId}</span>`</span>)
.<span class="hljs-title function_">expect</span>(<span class="hljs-number">200</span>);
});
});
</pre></div><h1 id="53b2">Conclusion:</h1><p id="36d8">This is a basic setup to create a CRUD application using NestJS with MongoDB and then test it. You can expand this app by adding validation, error handling, and other features as needed. The combination of NestJS and MongoDB offers powerful capabilities, and testing ensures that your application behaves as expected.</p></article></body>