news-focused.test.ts•4.5 kB
/**
* Focused unit tests for NewsController
*
* This approach simplifies mocking and improves test reliability
*/
import { describe, test, expect, beforeEach, jest, afterEach } from '@jest/globals';
import { Request, Response } from 'express';
// Mock the entire news service module before importing controller
jest.mock('../../services/news.service', () => ({
NewsService: jest.fn().mockImplementation(() => ({
getTopNews: jest.fn().mockResolvedValue({
data: [{ uuid: 'test-uuid', title: 'Test Article' }],
meta: { found: 1, returned: 1 }
}),
getAllNews: jest.fn().mockResolvedValue({
data: [{ uuid: 'test-uuid', title: 'Test Article' }],
meta: { found: 1, returned: 1, page: 1, limit: 10 }
}),
getNewsByUuid: jest.fn().mockImplementation((uuid) => {
if (uuid === 'existing-uuid') {
return Promise.resolve({
data: { uuid: 'existing-uuid', title: 'Test Article' }
});
} else {
return Promise.reject(new Error('Article not found'));
}
}),
getNewsSources: jest.fn().mockResolvedValue({
data: [{ id: 1, name: 'Test Source' }],
meta: { found: 1, returned: 1 }
})
}))
}));
// Import controller after setting up mocks
import { NewsController } from '../../controllers/news.controller';
// Skip actual cache operations
jest.mock('../../utils/cache', () => ({
cacheService: {
get: jest.fn(),
set: jest.fn(),
has: jest.fn(),
clear: jest.fn(),
deleteByPrefix: jest.fn(),
getStats: jest.fn().mockReturnValue({ hits: 0, misses: 0, keys: 0 })
}
}));
describe('NewsController - Core Tests', () => {
let controller: NewsController;
let req: Partial<Request>;
let res: Partial<Response>;
beforeEach(() => {
// Reset mocks
jest.clearAllMocks();
// Create controller instance
controller = new NewsController();
// Setup basic request/response mocks
req = {
query: {},
params: {}
};
res = {
status: jest.fn(() => res as any),
json: jest.fn()
};
});
afterEach(() => {
jest.clearAllMocks();
});
describe('getTopNews', () => {
test('returns 200 status with articles', async () => {
// Arrange - nothing to do as defaults are set in beforeEach
// Act
await controller.getTopNews(req as Request, res as Response);
// Assert
expect(res.status).toHaveBeenCalledWith(200);
expect(res.json).toHaveBeenCalledWith(
expect.objectContaining({
success: true,
data: expect.arrayContaining([
expect.objectContaining({ uuid: 'test-uuid' })
])
})
);
});
test('handles errors gracefully', async () => {
// Arrange - force the service to throw an error
const newsService = new (require('../../services/news.service').NewsService)();
newsService.getTopNews.mockRejectedValueOnce(new Error('Test error'));
// Override the controller to use our service with error
jest.spyOn(controller as any, 'newsService', 'get').mockReturnValue(newsService);
// Act
await controller.getTopNews(req as Request, res as Response);
// Assert
expect(res.status).toHaveBeenCalledWith(500);
expect(res.json).toHaveBeenCalledWith(
expect.objectContaining({
success: false,
error: expect.any(String)
})
);
});
});
describe('getNewsByUuid', () => {
test('returns 200 status with article when found', async () => {
// Arrange
req.params = { uuid: 'existing-uuid' };
// Act
await controller.getNewsByUuid(req as Request, res as Response);
// Assert
expect(res.status).toHaveBeenCalledWith(200);
expect(res.json).toHaveBeenCalledWith(
expect.objectContaining({
success: true,
data: expect.objectContaining({ uuid: 'existing-uuid' })
})
);
});
test('returns 404 status when article not found', async () => {
// Arrange
req.params = { uuid: 'non-existent-uuid' };
// Act
await controller.getNewsByUuid(req as Request, res as Response);
// Assert
expect(res.status).toHaveBeenCalledWith(404);
expect(res.json).toHaveBeenCalledWith(
expect.objectContaining({
success: false,
error: expect.any(String)
})
);
});
});
});