Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: mockito/mockito
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v4.10.0
Choose a base ref
...
head repository: mockito/mockito
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v4.11.0
Choose a head ref
  • 1 commit
  • 26 files changed
  • 1 contributor

Commits on Dec 28, 2022

  1. Add type() method to ArgumentMatcher (#2807)

    Using the new `type()`, we can differentiate between matching all varargs
    or only one argument of the varargs.
    
    # Benefits:
    
    Because this approach leaves `VarargsMatcher` untouched, it does not require additional existing matchers to implement `VarargsMatcher` to fix issues such as #567. Where as the first PR would require `Null` and `NotNull` to be marked `VarargsMatcher`.
    
    This PR creates new variants of `isNotNull` and `isNull` to address #567. 
    Having `InstanceOf` override `type()` provides a workable solution to #1593.
    Having `equals` override `type` addresses #1222.
    
    # Downsides
    
    The obvious downside is that this changes the public `ArgumentMatcher` interface, though in a backwards compatible way.
    
    ## Known limitation
    
    The main limitation I'm aware of, is not a new limitation. It is that it is not possible to assert only a single parameter is passed to the vararg parameter, when using a `VarargMatcher`, e.g. `any()`. (ref: #1593). For example:
    
    ```java
    // Given method:
    int vararg(String... args);
    
    // I want to mock this invocation:
    mock.vararag("one param");
    
    // ...but not these:
    mock.vararg();
    mock.vararg("more than", "one param");
    ```
    
    There is no current way to do this.  This is because in the following intuitive mocking:
    
    ```java
    given(mock.vararg(any(String.class))).willReturn(1);
    ```
    
    ... matches zero or more vararg parameters, as the `any()` method is using `VarargMatcher`. It seems to me that `VarargMatcher` is... a little broken!  This is maybe something that should be consider a candiate for fixing in the next major version bump.  
    
    While it is not possible to fix any `VarargMatcher` based matchers in a backwards compatible way, this the approach in this PR it is possible to mock/verify exactly one vararg param using `isA`, rather than `any`:
    
    ```java
        @test
        public void shouldMatchExactlyOnParam() {
            mock.varargs("one param");
    
            verify(mock).varargs(isA(String.class));
        }
    
        @test
        public void shouldNotMatchMoreParams() {
            mock.varargs("two", "params");
    
            verify(mock, never()).varargs(isA(String.class));
        }
    
        @test
        public void shouldMatchAnyNumberOfParams() {
            mock.varargs("two", "params");
    
            verify(mock).varargs(isA(String[].class));
        }
    
    ```
    
    ... because `isA` does not implement `VarargsMatcher`, and so can work as expected once it implements `type()`.
    
    Fixes #2796
    Fixes #567
    Fixes #584
    Fixes #1222
    Fixes #1498
    big-andy-coates authored and TimvdLippe committed Dec 28, 2022
    Configuration menu
    Copy the full SHA
    483e15f View commit details
    Browse the repository at this point in the history
Loading