Dartvel, home
Docs
Features
Studio
Cloud
Compared

Search the site

GitHub
pub.dev

GETTING STARTED

Getting started
Existing Flutter apps
Existing Native apps
Run on your phone

APP

UI and styling
Routing
State
Accessibility
Keyboard shortcuts
Localization
Devices and desktop
Native device access
Media, 3D and XR

DATA

Data models
Forms
Search
Sync and offline
Import and export
Change capture
Database
Cache
File storage
Images
Privacy and erasure

BACKEND

Backend functions
Auth and sessions
Authorization
Queues and jobs
Workers and memory
Notifications and mail
Outbound HTTP
AI
Webhooks
GraphQL and OpenAPI
API keys and OAuth
Multi-tenancy
Billing and commerce
Modules

OPERATIONS

Edge security
Secrets and environments
Monitoring
Releases

SHIPPING

Build targets
Telegram Mini Apps
Static web hosting
Servers and deploying

REFERENCE

Testing
CLI reference
Coding agents

REFERENCE

Testing

Test mail, HTTP calls, jobs and models without a network or a server.

Each DV.Test fake returns an object you can assert on.

ON THIS PAGE

A test with fakes

The fakes

Make records with generated factories

Run one kind of test

Reset between tests

Status

A test with fakes

import 'package:docs_samples/dartvel_client/dartvel_client.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  // Declares the hosts in pubspec.yaml, which the app does at startup.
  setUp(configureDartvelHttp);
  tearDown(DVHttp.reset);

  test('the welcome email is sent', () async {
    final DVMemoryMailProvider mail = DV.Test.fakeMail();

    await DV.Notifications.mail.send(const DVMailMessage(
      from: DVMailAddress('hello@example.com'),
      to: <DVMailAddress>[DVMailAddress('ada@example.com')],
      subject: 'Welcome',
      text: 'Hi Ada',
    ));

    expect(mail.sent.single.subject, 'Welcome');
  });

  test('a payment is verified against a stubbed host', () async {
    final DVHttpFake http = DV.Test.fakeHttp(<String, DVHttpStub>{
      'paystack': DVHttpStub.json(<String, Object?>{'status': true}),
    });

    final Response response =
        await DV.Http.host('paystack').get('/transaction/verify/ref-1');

    expect(response.status, 200);
    expect(http.calls, hasLength(1));
  });

  test('jobs run in memory', () async {
    DV.Test.fakeQueue();
    DV.Jobs.register<String>((String name) async {});
    await DV.Jobs.dispatch<String>('hello');
    expect(await DV.Jobs.pending(), hasLength(1));
  });
}

Copy code to clipboard

dartvel test
dartvel test --watch

Copy code to clipboard

The fakes

DV.Test.fakeMail()

Gives you: DVMemoryMailProvider, with .sent

DV.Test.fakeNotifications()

Gives you: DVMemoryNotificationProvider, with .sent

DV.Test.fakeHttp({...})

Gives you: DVHttpFake, with .calls, answering from DVHttpStub

DV.Test.fakeQueue()

Gives you: An in-memory queue

DV.Test.fakeDatabase()

Gives you: MemoryDVDatabaseAdapter

DV.Test.fakeStorage()

Gives you: DVMemoryFileStorageAdapter

DV.Test.fakeAuthUser()

Gives you: A DVAuthUser for asUser(...)

DV.Test.withSecrets({...}, body)

Gives you: Secrets for the length of body

DV.Test.fakeAI()

Gives you: LocalDVAIAdapter, with no provider called

DV.Test.fakeNativeBinding(name, handler)

Gives you: An answer for one DV.Platform binding

DV.Test.fakeWindowing(capability)

Gives you: The windowing a test declares, instead of the host's

DV.Test.fake3D() and DV.Test.fakeXR(...)

Gives you: A 3D scene without a GPU, and a fake XR device

DVHttpStub has json, text, status, timeout, error and sequence.

A host with no stub fails the call, so a test never reaches the network.

There is no cache fake: in a test DV.Cache is in memory. Call DV.Cache.delete(DVCache.all) in setUp.

Make records with generated factories

setUp(ProductFactory.resetSequence);

test('each product the factory makes is its own record', () {
  final List<Product> products =
      const ProductFactory(published: false).createMany(3);

  expect(products.map((Product p) => p.slug).toSet(), hasLength(3));
  expect(products.every((Product p) => !p.published), isTrue);
});

Copy code to clipboard

Every @DVModel gets a Factory class with create, createMany and admin.

Ids, emails and slugs carry a sequence, so two records never share one.

resetSequence starts the count again, so a snapshot comes out the same on every run.

Run one kind of test

dartvel test e2e
dartvel test golden --update-goldens
dartvel test --total-shards 4 --shard-index 0

Copy code to clipboard

unit (the default)

Looks in: test

e2e

Looks in: test/e2e, then integration_test

golden

Looks in: test/golden or test/goldens

native

Looks in: test/native, test/ffi or test/jni

accessibility

Looks in: test/accessibility or test/a11y

release

Looks in: test/release, then the e2e folders, then test

A mode with no tests says so and lists where it looked. It never runs the whole suite under that mode's name.

Reset between tests

DV.Test has resetQueues, resetMail, resetNotifications, resetPolicies, resetCacheTags, resetAuth, resetStorage, resetAI and resetNativeBindings. Call DVHttp.reset after an HTTP fake.

Status

Partial

Spec section: Testing

PREVIOUS Servers and deploying Run the backend, deploy and provision hosts
NEXT CLI reference Every dartvel command and flag
GitHub
pub.dev
npm
Acknowledgements
Privacy
Terms

FSL-1.1-MIT licensed. Built with Dartvel.

Dartvel is made by

SigmaDev Digital

To the bottom