簡體   English   中英

的Mockito。 如何基於模擬對象作為參數返回布爾值?

[英]Mockito. How to return a boolean value based on mocked object as parameter?

Class A
{
public B makeB(int q)
    {
        return new B(q);
    }
    public boolean evaluate(int q)
    {
        B b = makeB(q);
        boolean result = b.get();
        return result;
    }
}

Class B
{
    int e;
    public B(int w)
    {
        e=w;
    }
    public boolean get()
    {
        //return boolean based on object B
    } 
}

Class ATest
{
    A a = spy(A.class);
    B b1 = mock(B.class);
    B b2 = mock(B.class);

    doReturn(b1).when(a).makeB(5);
    doReturn(b2).when(a).makeB(10);

    when(b1.get()).thenReturn(true);
    when(b2.get()).thenReturn(false);

    a.evaluate();
}

=======================

在這里,我想在對象B包含值5時從方法評估返回true,而在對象B包含值10時返回false。

B類來自外部庫。

單元測試和模擬的新手。

其他答案在技術上是正確的,但首先要理解:您應該努力使用這樣的模擬框架。

請記住:模擬框架的目的僅僅是使測試變得容易/容易。 您的嘲笑規格應盡可能簡單。 含義:與其考慮讓模擬針對不同的參數給出不同的結果,不如考慮更好的解決方案是具有不同的測試和模擬規范,例如:

@Test 
public void testFooWithA() {
  when(someMock.foo(eq(whateverA)).thenReturn(bar);
  ...

@Test 
public void testFooWithB() {
  when(someMock.foo(eq(whateverB)).thenReturn(somethingElse);
  ...

在某些情況下,您編寫了更復雜的代碼以使模擬“更智能”。 但是大多數時候我必須這樣做-我退后一步, 簡化了我的測試設計。 換句話說:當您的測試變得“太復雜”時-最常見的原因是所測試的類/方法太復雜

您可以使用Mockito的Answer接口來實現。 它使您可以訪問call的實際參數,並可以基於該參數區分返回的值。

給定的界面

interface Measurer {
    int measureLength(String s);
}

一個示例用法可能看起來像

Measurer measurer = Mockito.mock(Measurer.class);
Mockito.when(measurer.measureLength(Mockito.any(String.class)))
        .then((Answer<Integer>) invocationOnMock -> {
            String arg = invocationOnMock.getArgumentAt(0, String.class);
            if (arg.length() < 10) {
                // mock Measurer can measure only short strings
                return arg.length();
            }
            else {
                return 42;
            }
        });

System.out.println(measurer.measureLength("abc")); // 3
System.out.println(measurer.measureLength("abcdefghijklmn")); // 42

在這種情況下,您可以執行以下操作:

doAnswer(new Answer<Boolean>() {
     public Boolean answer(InvocationOnMock invocation) {
         return invocation.getArgument(0) == 5;
     }}).when(a.evaluate());

如果您要問如何在A#evaluate()的實際實現中獲取'b'的實際值,則可以為兩個將本地變量設置為返回的B實例的模擬添加對makeB的答案,因此您知道上次調用它返回的內容,那么您可以根據該局部變量的值獲得對validate()返回的答案。

那是:

B lastB = null;
Answer<B> lastBAnswer = new Answer<B>() {
  public B answer(InvocationOnMock invocation) {
    if (invocation.<Integer>getArgument(0) == 5) {
      lastB = b1;
    } else {
      lastB = b2;
    }
    return lastB;
  }
};
doAnswer(lastBAnswer).when(a).makeB(any());
doAnswer(new Answer<Boolean>() {
  public Boolean answer(InvocationOnMock invocation) {
    return lastB.get();
  }
}).when(a).evaluate();

我不建議使用該路徑,因為它依賴於時間內聚,但是對於測試而言,它是可以接受的。

注意:通過StackOverflow回答而不進行語法檢查。 可能會略有偏離,但這是一個粗略的想法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM