2

I am migrating from mockito-all:1.9.5 to mockito-core:2.28.2, and some of the tests that were passing are now failing.

For example, this test :

@ExtendWith(CdiUnitExtension.class)
@AdditionalClasses({
    XmlMockUnmarshaller.class
})
public class FeaturesTest

    @Produces
    @Mock
    private RefService refService;
    
    @Produces
    @Mock
    private PaymentService paymentService;
    
    @BeforeEach
    public void setUp() {
        this.cacheData = new CacheData();
        this.cacheData.setDateExecution("12/12/2015");
        when(refService.isDateAvailable(anyString()).thenReturn(true);
    }
    
    @Test
    public void shouldReturnErrorIfReasonHasInvalidChars() {
        // Given
        this.cacheData.setReason("qhsdlq$98%èd");
    
        // When
        List<Error> errors = paymentService.validatePayment(this.cacheData);
    
        // Then
        assertTrue(errors.size() == 1); // test fails : errors.size() = 2;
        assertEquals(errors.get(0).getField(), "reason");
    }
}

with the method validatePayment being like :

@Inject
RefService refService;
...
public List<Error> validatePayment(CacheData cacheData) {
    ...
    if (!refService.isDateAvailable(cacheData.getExecutionDate())) {
        errors.add(new Error("executionDate"));
    }
    ...
    return errors;
}

With mockito-core, this test fails because there are 2 errors in the list, as if the configuration of the mock in the setUp is ignored.

How can I rewrite my test to make it pass ?

Progman
  • 16,827
  • 6
  • 33
  • 48
l0r3nz4cc10
  • 1,237
  • 6
  • 27
  • 50
  • 1
    You never pass your `refService` into your `paymentService` (at least you are not showing that part of the code). [Why is my class not calling my mocked methods in unit test?](https://stackoverflow.com/q/74027324/112968) could be useful – knittl Jan 12 '23 at 18:29
  • Sorry, I edited the code to show how refService is injected into paymentService – l0r3nz4cc10 Jan 13 '23 at 08:53
  • Can you check if `paymentService.refService` and `test.refService` are the same instance? You can check with a debugger or `System.out.println`+`System.identityHash`. What are the memory addresses of both fields? – knittl Jan 13 '23 at 08:56
  • 1
    Yes, they are the same instance, both `refService` share the same identityHash – l0r3nz4cc10 Jan 13 '23 at 14:19
  • Next question (I haven't noticed this earlier, sorry): What is the return type of `getExecutionDate()`? Is it really a string? Because your mock is set up to only react on string parameters, not any other types. Since the getter ends in `Date`, are you sure it returns a string and not a `java.util.Date` or `java.time.Instant`? – knittl Jan 13 '23 at 14:26
  • the return type of `getExecutionDate()` is really a String – l0r3nz4cc10 Jan 13 '23 at 14:48
  • If you set a breakpoint where `isDateAvailable` is called and then execute it with the debugger, is it false or true? And is the string `null` or an actual string literal? `anyString()` will NOT match nulls. – knittl Jan 13 '23 at 14:53
  • `isDateAvailable(cacheData.getExecutionDate())` evaluates to `false` when debugging, and the string is an actual string literal (I omitted its setting in cacheData in the setup method because I didn't think it was relevant, I've added it) – l0r3nz4cc10 Jan 13 '23 at 15:08
  • Asked differently, what is the value of `new CacheData().getExecutionDate()`? I bet it is `null` – knittl Jan 13 '23 at 15:08
  • Can you share the test class definition and its annotations? Also, what version of JUnit are you using for the test? – Mureinik Jan 13 '23 at 15:14
  • @knittl : I mean, I omitted `this.cacheData.setDateExecution("12/12/2015");` in the question, it was always there in my code – l0r3nz4cc10 Jan 13 '23 at 15:26
  • @Mureinik : I am using junit-jupiter-api:5.9.1 – l0r3nz4cc10 Jan 13 '23 at 15:31
  • @l0r3nz4cc10 you could also try changing `thenReturn` to `thenAnswer` and setting a breakpoint in the lambda to see if it is being executed. `false` means that the configured return is not being used. – knittl Jan 13 '23 at 15:49

1 Answers1

0

It looks like you're missing the MockitoExtension (which for you case should be provided by the org.mockito:mockito-junit-jupiter:jar:2.28.2 dependency needed for Mockito to handle the @Mock annotations:

@ExtendWith({MockitoExtension.class, CdiUnitExtension.class})
// Here -----^
@AdditionalClasses({
    XmlMockUnmarshaller.class
})
public class FeaturesTest
Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • But if the mockito extension is missing, the field should never be set at all to a mock? According to the comments, the field is already set. – knittl Jan 13 '23 at 15:46