next thenReturn 仍然是 returns 之前 thenThrow 的结果

next thenReturn still returns previous result of thenThrow

我看到类似的问题,例如 和其他有答案的问题,但 accepted/voted 的答案对我不起作用。 Class 传出依赖于 TransManager,我想模拟它的方法。

现在测试 deleteInvoiceReIssue 失败了,因为 mock.thenReturn() 没有效果。反而还记得之前的thenThrow

我确实在一次测试中尝试使用嵌套 returns(thenThrow 和 thenReturn),但也没有发现任何区别。

package com.invoicestracker;

@RunWith(MockitoJUnitRunner.class)
public class OutgoingTest {
    private static String cPoint = "test";
    private TransManager mockedTransManager;
    private Outgoing mockedOutgoing;


    @Before
    public void setUp(){
        mockedTransManager = mock(TransManager.class);
        mockedOutgoing = new Outgoing(context, mockedTransManager);
    }


    @After
    public void recreateMocks(){
        reset(mockedTransManager);
        mockedTransManager = mock(TransManager.class);
        mockedOutgoing = new Outgoing(context, mockedTransManager);
    }



    @Test
    public void deleteInvoice() {
        //InvoiceException is a custom exception
        InvoiceException ex = new InvoiceException("Invoice Exception");
        when(mockedTransManager.deleteInvoice(any()))
                .thenThrow(ex);
        Boolean result = mockedOutgoing.deleteInvoice(cPoint, false);
        assertThat(result).isEqualTo(false);
    }

    @Test
    public void deleteInvoiceReIssue() {
        //the mock below always returns an exception from the above  
        when(mockedTransManager.deleteInvoice(any())).thenReturn(true);
       Boolean result =  mockedOutgoing.deleteInvoice(cPoint, true);
       assertThat(result).isEqualTo(true); //fails, expected true but got false
    }

    // also tried
    
    @Test
    public void deleteInvoice() {
        //InvoiceException is a custom exception
        InvoiceException ex = new InvoiceException("Invoice Exception");
        when(mockedTransManager.deleteInvoice(any()))
                .thenThrow(ex)
                .thenReturn(true);
        Boolean result = mockedOutgoing.deleteInvoice(cPoint, false);
        assertThat(result).isEqualTo(false);

        //delete with reissue.
         Boolean result =  mockedOutgoing.deleteInvoice(cPoint, true);
       assertThat(result).isEqualTo(true);
    }
}

你似乎在测试 Outgoing 所以它不是模拟坚果它在内部使用模拟。您可以使用 Mockito 注释进行测试,例如:

@Mock
private TransManager mockedTransManager;
@Mock
private Context context;
@InjectMocks // sets above mocks to outgoing
private Outgoing outgoing;

这会让您的 @Before@After 变得无用。

我假设InvoiceException extends RuntimeException因为你还没有申报任何throws。通过以上更改和假设,我可以毫无问题地进行这些工作:

@Test(expected = InvoiceException.class)
public void deleteInvoice() throws InvoiceException {
    InvoiceException ex = new InvoiceException("Invoice Exception");
    when(mockedTransManager.deleteInvoice(any())).thenThrow(ex);
    outgoing.deleteInvoice(cPoint, false);
}

@Test
public void deleteInvoiceReIssue() {
    when(mockedTransManager.deleteInvoice(any())).thenReturn(true);
    assertTrue(outgoing.deleteInvoice(cPoint, true));
}