0

我正在为一种方法编写单元测试,如果在我的 twilio 帐户上已经找到子帐户,则该方法返回 true。我正在尝试使用 Mockito 来模拟它,但在将 List 转换为 AccountList 时出现转换错误。我查看了 mockito 文档,但可能遗漏了一些东西。

这是测试:

        @Mock
TwilioRestClient client;

@Mock
AccountList accountList;

@Mock
Iterator<Account> iterator;

@Mock
Account account;

@Test
public void testShouldReturnTrueIfAccountNameFound() {
        final List<Account> list = Arrays.asList(account);

        when(client.getAccounts()).thenReturn((AccountList) list);
        when(account.getFriendlyName()).thenReturn("test");
        when(accountList.iterator()).thenReturn(list.iterator());
    MyTwilioAccountStore store = null;
    store = new MyTwilioAccountStore(client);

    Assert.assertTrue(store.subAccountExists("test"));  
}

这就是我正在测试的方法。我在构造函数中注入了 TwilioRestClient。

        /**
 * class constructor
 * 
 * @param client
 */
public MyTwilioAccountStore(TwilioRestClient client) {
    fClient = client;
}


/**
 * rest client getter
 * 
 * @return RESTClient
 */
public TwilioRestClient getRestClient() {
    return fClient;
}
     /**
 * Check if a sub account already exists
 * 
 * @param friendlyName
 * @return boolean
 */
public boolean subAccountExists(String friendlyName) {
    // Build a filter for the AccountList
    Map<String, String> params = new HashMap<String, String>();
    params.put("FriendlyName", friendlyName);
    AccountList accounts = getRestClient().getAccounts(params);

    // Loop over accounts
            // This is where I get NPE
    for (Account account : accounts) {
        if (account.getFriendlyName().equalsIgnoreCase(friendlyName)) {
            return true;
        }
    }

    return false;
}

这是 Twilio 源代码的 getAccounts:

    /**
 * Get all accounts. For more info: {@link <a
 * href="http://www.twilio.com/docs/api/rest/account"
 * >http://www.twilio.com/docs/api/rest/account</a>}
 *
 * @return the list of accounts.
 */
public AccountList getAccounts() {
    return this.getAccounts(new HashMap<String, String>());
}

如何正确模拟 AccountList?

4

2 回答 2

1

编辑这里真正的问题似乎是能够模拟AccountList,从 twilio 客户端返回......

编辑继续_ Iterable<Account>_ Account_ _accountList.iterator()Iterator


原始答案

你嘲笑:

when(accountList.iterator().next())

但是,当您使用 foreach 循环时,首先调用的是.iterator()它本身——而您对此没有任何模拟。作为返回,mockito 执行默认操作:返回null(老实说,我真的很惊讶它甚至没有在这里抛出异常告诉“抱歉,不能这样做”,因为它是一个链式方法调用!)。

你应该:

when(accountList.iterator()).thenReturn(anIterator);

whereanIterator是一个实际的迭代器,带有.hasNext(),.next().remove()

由于您似乎也想为您的帐户使用模拟,我想您的列表应该这样设置:

final List<Account> accountList = Arrays.asList(account);

这使:

@Test
public void shouldReturnTrueIfAccountNameFound() 
{
    final List<Account> list = Arrays.asList(account);

    when(account.getFriendlyName()).thenReturn("test");
    when(accountList.iterator()).thenReturn(list.iterator());

    final MyTwilioAccountStore store = new MyTwilioAccountStore(client);

    Assert.assertTrue(store.subAccountExists("test"));  
}
于 2013-06-11T17:21:07.630 回答
1

在我看来,你做错了。仅仅因为你@Mock在一个字段上说,并不意味着任何实例化相同类型的类的东西都会得到它。您需要找到一种方法getRestClient()来返回您的模拟。如果它返回 a new AccountList,那将不是你的模拟,它可能会导致这些问题。

向我们展示getRestClient()方法,我可以提供更多帮助。


好的,你有一个getAccounts()用这一行模拟的方法:

    when(client.getAccounts()).thenReturn((AccountList) list);

但是被测系统调用了这一行:

    AccountList accounts = getRestClient().getAccounts(params);

看到这里的区别了吗?被调用的实际方法接受 a Map,但您不是在模拟该方法。您需要将上面的 when 更改为以下内容:

    when(client.getAccounts(any(Map.class))).thenReturn((AccountList) list);

换句话说,你在嘲笑错误的方法。默认情况下,Mockito 将返回合理的默认值,在这种情况下,它恰好是null. 如果getAccounts()返回 Integer/int,它将返回 0。

于 2013-06-11T17:21:54.587 回答