Menü der Dokumentation

Testen von d.velop-Apex-Code

In Apex kannst du Unit- und Integration-Tests auf verschiedene Arten und Weisen schreiben. Salesforce bietet dir mehrere Möglichkeiten, Tests effizient, sicher und zuverlässig zu gestalten.

In diesem Kapitel erfährst du, wie du deine verwendeten Apex-Klassen in deinen Tests erfasst. Außerdem erfährst du, auf was du dabei achten musst, um Probleme zu vermeiden.

Inhalt
Generieren der Testumgebung

Der Aufbau und das Einfügen von Testdaten ist häufig aufwändig und ineffizient. Vermeide diesen Aufwand bei Unit-Tests, da schlecht aufgebaute Unit-Tests meist teuer und unübersichtlich sind.

Anmerkung

Wie du ineffizient generierte Testdaten und unabhängige, isolierte Unit-Tests vermeidest, erfährst du im Kapitel Verwenden von Mocks für isolierte Unit-Tests.

Verwende für Integration- oder Unit-Tests mit Zugriff auf Testdaten die Klasse dvelop_docs_dev.OpenAPI. Die Methode initializeTestEnvironment() sorgt dafür, dass nur wenige Testdaten und HTTP-Callout-Mocks aufgebaut werden. Auf diese Weise kannst du die d.velop-Klassen und Methoden erfolgreich in deinen Tests aufrufen.

Im folgenden Beispiel erfährst du, wie du die Methode verwendest:

@IsTest
private class MyTestClass {
	@TestSetup // Notice the "TestSetup" annotation
	static void makeData() {
		dvelop_docs_dev.OpenAPI.initializeTestEnvironment();
	}

	@IsTest
	static void myUnitTest() {
		// TODO: implement unit test
	}
}
Verwenden von Mocks für isolierte Unit-Tests

Das sogenannte Mocking ist ein häufig verwendetes Muster in der Softwareentwicklung, um effiziente, isolierte und zuverlässige Unit-Tests schreiben zu können. Aus diesem Grund wurden Mocking-Frameworks wie Javas Mockito entwickelt.

Auch mit Salesforce kannst du Abhängigkeiten zwischen Apex-Klassen mithilfe der Stub API simulieren. Auf diese Weise kannst du Tests unabhängig voneinander und ohne voriges Einfügen von Testdaten durchführen. ApexMocks  ist eines der führenden Mocking-Frameworks, das sich stark an Mockito orientiert und auf dem Konzept der Dependency Injection basiert.

Du kannst Abhängigkeiten zwischen Klassen in Salesforce auch ohne Frameworks mit der Stub API simulieren, etwa d.velop-Klassen wie z.B. dvelop_docs_dev.DocumentManager.

Anmerkung

Beim Simulieren einer Apex-Klasse mit der Stub API kannst du lediglich nicht-statische Methoden simulieren. Klassen wie dvelop_docs_dev.OpenAPI können aufgrund ihres ausschließlich statischen Aufbaus nicht effektiv mit der Stub API oder etwaigen Frameworks simuliert werden.

Nachfolgend findest du ein Beispiel, in dem die Stub API ohne Framework zusammen mit d.velop-Klassen verwendet wird.

Verwenden der Stub API mit d.velop-Klassen

In diesem Beispiel sollen Unit-Tests für die Klasse MyConsumerClass geschrieben werden. Diese Klasse verwendet die Methode getDocument(documentId) der Klasse DocumentManager und ist von der jeweiligen Methode abhängig. Ein Unit-Test ohne Mocking stellt sicher, dass alle notwendigen Testdaten und HTTP-Mocks generiert und festgelegt sind.

public with sharing class MyConsumerClass {
	private final dvelop_docs_dev.DocumentManager docManager;

	// The document manager is injected into the constructor as a dependency
	public MyConsumerClass(dvelop_docs_dev.DocumentManager docManager) {
		this.docManager = docManager;
	}

	public dvelop_docs_dev.Document doSomeMagic(String documentId) {
		if (String.isBlank(documentId)) {
			throw new System.IllegalArgumentException('Document ID must not be blank');
		}

		return docManager.getDocument(documentId);
	}
}

Durch die Verwendung der Stub API kannst du diese Abhängigkeit durch einen Stub ersetzen. Dafür erstellst du eine Hilfsklasse, die das System.StubProvider-Interface verwendet. Genauere Details und Hinweise zur Verwendung des Interfaces erhältst du im Apex-Leitfaden.

@IsTest
public class MyStubProvider implements System.StubProvider {
	// Implement the handleMethodCall method
	public Object handleMethodCall(
		Object stubbedObject,
		String stubbedMethodName,
		Type returnType,
		List<Type> listOfParamTypes,
		List<String> listOfParamNames,
		List<Object> listOfArgs
	) {
		// Check the name of the called method on the mocked instance (dvelop_docs_dev.DocumentManager) and return a mocked value
		switch on stubbedMethodName {
			when 'getDocument' {
				dvelop_docs_dev.Document mockedDocument = new dvelop_docs_dev.Document();
				mockedDocument.id = '123';
				return mockedDocument;
			}
			when else {
				return null;
			}
		}
	}
}

Abschließend können die Tests für die Klasse MyConsumerClass mit OpenAPI.createStub(parentType, stubProvider) auf den Provider (MyStubProvider) und auf die simulierten Rückgabewerte zugreifen.

Anmerkung

Da die Stub API lediglich die Erstellung von Stubs für Klassen im selben Namespace erlaubt, musst du den Aufruf innerhalb der Klasse OpenAPI im Namespace dvelop_docs_dev durchführen, anstelle Test.createStub(parentType, stubProvider) aufzurufen.

@IsTest
private class MyTestClass {
	static dvelop_docs_dev.DocumentManager stubbedManager = (dvelop_docs_dev.DocumentManager) dvelop_docs_dev.OpenAPI.createStub(
		dvelop_docs_dev.DocumentManager.class,
		new MyStubProvider()
	);

	static MyConsumerClass underTest = new MyConsumerClass(stubbedManager);

	@IsTest
	static void myUnitTest() {
		Test.startTest();
		dvelop_docs_dev.Document result = underTest.doSomeMagic('123');
		Test.stopTest();

		Assert.areEqual('123', result.id, 'Document ID should be 123');
	}
}