Over 27 years of development, I've seen testing practices evolve dramatically. From manual QA to comprehensive automated test suites, here's what I've learned about building reliable test strategies for enterprise applications.
The Testing Pyramid
A solid testing strategy follows the testing pyramid - lots of unit tests, fewer integration tests, and minimal end-to-end tests.
Unit Tests with Jest
Jest has become my go-to testing framework for JavaScript/TypeScript applications. Here's how we structured tests at Nutrien:
// CustomButton.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import '@testing-library/jest-dom';
import { CustomButton } from './CustomButton';
describe('CustomButton', () => {
it('renders with correct text', () => {
render(<CustomButton title="Click Me" onPress={jest.fn()} />);
expect(screen.getByText('Click Me')).toBeInTheDocument();
});
it('calls onPress when clicked', () => {
const mockOnPress = jest.fn();
render(<CustomButton title="Click Me" onPress={mockOnPress} />);
fireEvent.click(screen.getByRole('button'));
expect(mockOnPress).toHaveBeenCalledTimes(1);
});
it('shows loading state correctly', () => {
render(
<CustomButton title="Submit" onPress={jest.fn()} loading={true} />
);
expect(screen.queryByText('Submit')).not.toBeInTheDocument();
expect(screen.getByRole('status')).toBeInTheDocument(); // ActivityIndicator
});
it('is disabled when loading', () => {
const mockOnPress = jest.fn();
render(
<CustomButton title="Submit" onPress={mockOnPress} loading={true} />
);
fireEvent.click(screen.getByRole('button'));
expect(mockOnPress).not.toHaveBeenCalled();
});
it('applies correct variant styles', () => {
const { container, rerender } = render(
<CustomButton title="Primary" onPress={jest.fn()} variant="primary" />
);
expect(container.firstChild).toHaveClass('button-primary');
rerender(
<CustomButton title="Danger" onPress={jest.fn()} variant="danger" />
);
expect(container.firstChild).toHaveClass('button-danger');
});
});Testing Services with Mocks
Service layer tests require mocking external dependencies:
// referrals.service.test.ts
import { ReferralsService } from './referrals.service';
import { PrismaService } from '../prisma/prisma.service';
import { EmailService } from '../email/email.service';
// Mock the dependencies
jest.mock('../prisma/prisma.service');
jest.mock('../email/email.service');
describe('ReferralsService', () => {
let service: ReferralsService;
let prisma: jest.Mocked<PrismaService>;
let emailService: jest.Mocked<EmailService>;
beforeEach(() => {
// Create mock instances
prisma = new PrismaService() as jest.Mocked<PrismaService>;
emailService = new EmailService() as jest.Mocked<EmailService>;
service = new ReferralsService(prisma, emailService);
});
afterEach(() => {
jest.clearAllMocks();
});
describe('create', () => {
it('creates a referral and sends email notification', async () => {
const mockReferral = {
id: '123',
motherName: 'Jane Doe',
status: 'pending',
priority: 'HIGH',
userId: 'user123',
createdAt: new Date(),
updatedAt: new Date(),
};
const createDto = {
motherName: 'Jane Doe',
priority: 'HIGH',
userId: 'user123',
coordinatorEmail: 'coordinator@example.com',
};
// Mock Prisma response
prisma.referral.create.mockResolvedValue(mockReferral);
// Mock email service
emailService.sendReferralNotification.mockResolvedValue(undefined);
const result = await service.create(createDto);
// Verify Prisma was called correctly
expect(prisma.referral.create).toHaveBeenCalledWith({
data: expect.objectContaining({
motherName: 'Jane Doe',
priority: 'HIGH',
}),
include: expect.any(Object),
});
// Verify email was sent
expect(emailService.sendReferralNotification).toHaveBeenCalledWith(
'coordinator@example.com',
expect.objectContaining({
motherName: 'Jane Doe',
priority: 'HIGH',
})
);
expect(result).toEqual(mockReferral);
});
it('still creates referral if email fails', async () => {
const mockReferral = {
id: '123',
motherName: 'Jane Doe',
status: 'pending',
priority: 'HIGH',
userId: 'user123',
createdAt: new Date(),
updatedAt: new Date(),
};
prisma.referral.create.mockResolvedValue(mockReferral);
emailService.sendReferralNotification.mockRejectedValue(
new Error('Email service down')
);
// Should not throw - email failure shouldn't break referral creation
const result = await service.create({
motherName: 'Jane Doe',
priority: 'HIGH',
userId: 'user123',
coordinatorEmail: 'coordinator@example.com',
});
expect(result).toEqual(mockReferral);
});
});
describe('findByPriority', () => {
it('returns referrals filtered by priority', async () => {
const mockReferrals = [
{ id: '1', priority: 'HIGH', motherName: 'Jane' },
{ id: '2', priority: 'HIGH', motherName: 'Mary' },
];
prisma.referral.findMany.mockResolvedValue(mockReferrals as any);
const result = await service.findByPriority('HIGH');
expect(prisma.referral.findMany).toHaveBeenCalledWith({
where: { priority: 'HIGH' },
include: expect.any(Object),
orderBy: { createdAt: 'desc' },
});
expect(result).toEqual(mockReferrals);
});
});
});Integration Tests
Integration tests verify that multiple parts work together:
// referrals.integration.test.ts
import { Test } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from '../app.module';
import { PrismaService } from '../prisma/prisma.service';
describe('Referrals (Integration)', () => {
let app: INestApplication;
let prisma: PrismaService;
beforeAll(async () => {
const moduleRef = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleRef.createNestApplication();
await app.init();
prisma = app.get(PrismaService);
});
afterAll(async () => {
await app.close();
});
beforeEach(async () => {
// Clean database before each test
await prisma.referral.deleteMany();
await prisma.user.deleteMany();
});
describe('POST /referrals', () => {
it('creates a new referral', async () => {
// Create a test user
const user = await prisma.user.create({
data: {
email: 'test@example.com',
firstName: 'Test',
lastName: 'User',
role: 'ADVOCATE',
passwordHash: 'hashed',
},
});
const response = await request(app.getHttpServer())
.post('/referrals')
.set('Authorization', `Bearer ${testToken}`)
.send({
motherName: 'Jane Doe',
priority: 'HIGH',
userId: user.id,
notes: 'Urgent case',
})
.expect(201);
expect(response.body).toMatchObject({
motherName: 'Jane Doe',
priority: 'HIGH',
status: 'pending',
});
// Verify in database
const referral = await prisma.referral.findUnique({
where: { id: response.body.id },
});
expect(referral).toBeTruthy();
expect(referral.motherName).toBe('Jane Doe');
});
it('returns 401 without authentication', async () => {
await request(app.getHttpServer())
.post('/referrals')
.send({
motherName: 'Jane Doe',
priority: 'HIGH',
})
.expect(401);
});
});
});Enzyme for React Native
At Nutrien, we used Enzyme alongside Jest for React Native components:
// DatePicker.enzyme.test.tsx
import { shallow, mount } from 'enzyme';
import { DatePicker } from './DatePicker';
describe('DatePicker (Enzyme)', () => {
it('renders correctly', () => {
const wrapper = shallow(
<DatePicker value={new Date()} onChange={jest.fn()} />
);
expect(wrapper.find('TouchableOpacity')).toHaveLength(1);
});
it('opens modal when pressed', () => {
const wrapper = shallow(
<DatePicker value={new Date()} onChange={jest.fn()} />
);
expect(wrapper.find('Modal').prop('visible')).toBe(false);
wrapper.find('TouchableOpacity').simulate('press');
expect(wrapper.find('Modal').prop('visible')).toBe(true);
});
it('calls onChange with selected date', () => {
const mockOnChange = jest.fn();
const wrapper = mount(
<DatePicker value={new Date('2024-01-01')} onChange={mockOnChange} />
);
const newDate = new Date('2024-12-31');
wrapper.find('DateTimePicker').prop('onChange')(null, newDate);
expect(mockOnChange).toHaveBeenCalledWith(newDate);
});
});Testing Best Practices
1. Test Behavior, Not Implementation
// Bad - tests implementation
it('calls setState with the correct value', () => {
const wrapper = shallow(<Counter />);
wrapper.instance().setState = jest.fn();
wrapper.find('button').simulate('click');
expect(wrapper.instance().setState).toHaveBeenCalledWith({ count: 1 });
});
// Good - tests behavior
it('increments counter when button is clicked', () => {
render(<Counter />);
fireEvent.click(screen.getByRole('button'));
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});2. Use Data-Driven Tests
describe('formatPhoneNumber', () => {
it.each([
['1234567890', '+1 (123) 456-7890'],
['+11234567890', '+1 (123) 456-7890'],
['123-456-7890', '+1 (123) 456-7890'],
['(123) 456-7890', '+1 (123) 456-7890'],
])('formats %s as %s', (input, expected) => {
expect(formatPhoneNumber(input)).toBe(expected);
});
});3. Maintain Test Fixtures
// test/fixtures/users.ts
export const testUsers = {
admin: {
id: 'admin-1',
email: 'admin@example.com',
role: 'ADMIN',
firstName: 'Admin',
lastName: 'User',
},
coordinator: {
id: 'coord-1',
email: 'coordinator@example.com',
role: 'COORDINATOR',
firstName: 'Coordinator',
lastName: 'User',
},
};
// Use in tests
import { testUsers } from '../fixtures/users';
it('allows admin to view all referrals', async () => {
const response = await request(app.getHttpServer())
.get('/referrals')
.set('Authorization', `Bearer ${getTokenFor(testUsers.admin)}`)
.expect(200);
});CI/CD Integration
Tests are only valuable if they run automatically:
# .circleci/config.yml
version: 2.1
jobs:
test:
docker:
- image: circleci/node:16
- image: circleci/postgres:13
environment:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: test_db
steps:
- checkout
- restore_cache:
keys:
- v1-dependencies-{{ checksum "package.json" }}
- run: npm install
- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ checksum "package.json" }}
- run:
name: Run unit tests
command: npm test -- --coverage
- run:
name: Run integration tests
command: npm run test:integration
- store_test_results:
path: test-results
- store_artifacts:
path: coverage
workflows:
version: 2
test-and-deploy:
jobs:
- testConclusion
Good testing isn't about achieving 100% coverage - it's about testing the right things in the right ways. Focus on testing behavior, maintain clear test code, and integrate testing into your development workflow.
After 27 years, I can say with confidence: the upfront investment in testing pays massive dividends in reduced bugs, easier refactoring, and better sleep at night.

Jason Cochran
Sofware Engineer | Cloud Consultant | Founder at Strataga
27 years of experience building enterprise software for oil & gas operators and startups. Specializing in SCADA systems, field data solutions, and AI-powered rapid development. Based in Midland, TX serving the Permian Basin.