All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.roscopeco.moxy.api.MoxyVoidStubber Maven / Gradle / Ivy

There is a newer version: 0.94.0
Show newest version
/*
 * Moxy - Lean-and-mean mocking framework for Java with a fluent API.
 *
 * Copyright 2018 Ross Bamford
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 *   The above copyright notice and this permission notice shall be included
 *   in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.roscopeco.moxy.api;

import java.util.List;
import java.util.function.Consumer;

/**
 * 

Special case stubber for void methods. Does not allow a return * value to be set.

* *

Implementations of this are returned by the * {@link MoxyEngine#when(com.roscopeco.moxy.api.InvocationRunnable)} * method

* * @author Ross Bamford <roscopeco AT gmail DOT com> * @since 1.0 */ public interface MoxyVoidStubber { /** *

Stubs the mock invocation to throw the given Throwable.

* *

Note that mocks may be stubbed to throw any throwable - * checked or unchecked - irrespective of the method's throws * clause. This should be used with caution as undeclared checked * exceptions may cause undefined behaviour in callers.

* *

This method may be chained with other then... methods, * which will cause the mocked invocation to exhibit the chained * behaviours, in order, upon multiple calls to the mock.

* *

See {@link MoxyStubber#thenReturn(Object)} for a example of chained stubbing.

* * @param throwable The Throwable to throw for matching invocations. * * @return this, for ongoing stubbing. * * @since 1.0 */ public MoxyVoidStubber thenThrow(Throwable throwable); /** *

Instead of stubbing, have the mock call the real method instead.

* *

When this method is used to have mocks call their real methods, * verification is unaffected. In other words, you may verify these * mocks in the same way as any other.

* *

For obvious reasons, this will only work where the mocked method * is not abstract. If it is, an * {@link InvalidStubbingException} will be thrown when the mock is invoked.

* *

This method may be chained with other then... methods, * which will cause the mocked invocation to exhibit the chained * behaviours, in order, upon multiple calls to the mock.

* *

See {@link MoxyStubber#thenReturn(Object)} for a example of chained stubbing.

* * @return this, for ongoing stubbing. * * @since 1.0 */ public MoxyVoidStubber thenCallRealMethod(); /** *

Have this method delegate calls to the first compatible method on * the given object.

* *

When this is applied to a mocked method, all calls will be delegated * to an appropriate method on the given object. That means the method * will:

* *
    *
  • Not be static.
  • *
  • Be accessible, given the current security context (if applicable).
  • *
  • Have exactly the same name as the mocked method.
  • *
  • Have exactly the same return type as the mocked method.
  • *
  • Have exactly the same number of arguments as the mocked method.
  • *
  • Have exactly the same argument types as the mocked method.
  • *
* *

When determining which method to call, inherited methods are not * considered - only methods declared on the class of the supplied object are * taken into account, regardless of their access modifiers.

* *

While in practice the supplied delegate will often be an object of the * same class as the mock, this is not a requirement - the delegate can be * of any type, and multiple methods on the same mock may each delegate to * different objects, each of potentially different classes.

* *

This method may be chained with other then... methods, * which will cause the mocked invocation to exhibit the chained * behaviours, in order, upon multiple calls to the mock.

* *

See {@link MoxyStubber#thenReturn(Object)} for a example of chained stubbing.

* * @param delegate An object with a compatible method. * * @return this, for ongoing stubbing. * * @since 1.0 */ public MoxyVoidStubber thenDelegateTo(final Object delegate); /** *

Add a doAction to this method.

* *

doActions are arbitrary actions that are executed, in order, * during invocation of mocked methods. These actions can be applied to * any mock, including those that use {@link #thenCallRealMethod()}.

* *

The action receives the actual arguments the method was * called with as an immutable List.

* *

It is possible to chain multiple actions on a single invocation, * for example:

* *

   *   Moxy.when(() -> mock.something("arg"))
   *       .thenDo(args -> System.out.println("mock.something called"))
   *       .thenDo(args -> customRecorder.record("something", args))
   *       .thenCallRealMethod();
   * 
* *

Note: For a given invocation, all matching doActions * will be invoked, even if they weren't (intentionally) applied to the * given arguments. This only applies when argument matchers are used.

* *

As an example of this potentially-confusing behaviour, consider the * following example:

* *

   *   Moxy.when(() -> mock.hasTwoArgs(Matchers.any(), Matchers.eqInt(5)))
   *     .thenDo(() -> System.out.println("Action 1"));
   *     .thenDo(() -> System.out.println("Action 2"));
   *
   *   Moxy.when(() -> mock.hasTwoArgs(Matchers.eq("Bill"), Matchers.anyInt()))
   *     .thenDo(() -> System.out.println("Action 3"));
   *
   *   mock.hasTwoArgs("Bill", 5);
   * 
* *

In this example, the invocation mock.hasTwoArgs("Bill", 5) matches * both stubbed invocations, so all actions will run, resulting in the * following output:

* *

   *   Action 1
   *   Action 2
   *   Action 3
   * 
* *

I.e., since the framework has no way to tell exactly which of the two * potential matching preconditions you actually wanted, it calls them both.

* *

For this reason, you should exercise caution when using matchers with * doActions, to ensure you only execute actions on the invocations * you actually want to invoke them on. This is especially true where your * actions have side effects.

* * @since 1.0 * @param action The action, usually as a lambda. * * @return this, for continued stubbing. */ public MoxyVoidStubber thenDo(Consumer> action); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy