Mocking twilio with mockito



我正在编写一个单元测试,如果在我的twilio帐户上已经找到子帐户,则返回true的方法。我试图用Mockito模拟这个,但得到cast错误,将列表转换为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 ?

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

告诉我们getRestClient()方法,我可以帮助更多。


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

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

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

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

看到区别了吗?实际被调用的方法接受一个Map,但是你没有嘲笑那个方法。你需要把上面的when改成这样:

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

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

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

EDIT continue 如果,正如我猜想的那样,该类实现了Iterable<Account>,那么需要的是用模拟Account构建一个单元素列表,并让accountList.iterator()返回上面创建的列表的Iterator


原始回答

你模拟:

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

但是当您使用foreach循环时,首先调用的是.iterator()本身—并且您没有mock。作为返回,mockito执行默认操作:返回null(说实话,我真的很惊讶,它甚至没有抛出一个异常,告诉"对不起,不能这样做",因为它是一个链式方法调用!)。

你应该:

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

其中anIterator是一个实际的迭代器,包括.hasNext().next().remove()

既然你似乎也想为你的帐户使用mock,我猜你的列表应该这样设置:

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"));  
}

相关内容

  • 没有找到相关文章

最新更新