@Test
    public void whenSuspendAllFails() {
        // A spy is preferential because suspendAll() relies on delegating the hard work to suspend() and resume().
        OrchestratorImpl orchestrator = spy(this.orchestrator);

        Throwable supensionFailure = new HostStateChangeDeniedException(
                DummyServiceMonitor.TEST6_HOST_NAME,
                "some-constraint",
                "error message");
        doThrow(supensionFailure).when(orchestrator).suspendGroup(any(), eq(DummyServiceMonitor.TEST6_NODE_GROUP));

        try {
            orchestrator.suspendAll(
                    new HostName("parentHostname"),
                    List.of(
                            DummyServiceMonitor.TEST1_HOST_NAME,
                            DummyServiceMonitor.TEST3_HOST_NAME,
                            DummyServiceMonitor.TEST6_HOST_NAME));
            fail();
        } catch (BatchHostStateChangeDeniedException e) {
            assertEquals("Failed to suspend NodeGroup{application=tenant-id-3:application-instance-3:prod:utopia-1:default, " +
                            "hostNames=[test6.hostname.tld]} with parent host parentHostname: " +
                            "Changing the state of test6.hostname.tld would violate " +
                            "some-constraint: error message",
                    e.getMessage());
        }

        InOrder order = inOrder(orchestrator);
        order.verify(orchestrator).suspendGroup(any(), eq(DummyServiceMonitor.TEST3_NODE_GROUP));
        order.verify(orchestrator).suspendGroup(any(), eq(DummyServiceMonitor.TEST6_NODE_GROUP));
        order.verifyNoMoreInteractions();
    }
Test Orchestrator with a mock backend (the MockCurator)

@author smorgrav
orchestrator/src/test/java/com/yahoo/vespa/orchestrator/OrchestratorImplTest.java