Система ошибок модульного тестирования.Исключение InvalidCastException:

#c# #unit-testing #asp.net-core

#c# #модульное тестирование #asp.net-core

Вопрос:

Я тестирую метод, который вызывает функцию из моего репозитория и возвращает ее в виде списка, но я продолжаю получать эту ошибку:

Система.Исключение InvalidCastException: невозможно привести объект типа ‘System.Коллекции.Generic.List`1[System.Строка] ‘ для ввода’системы.Строка[]’.

Я не знаю, чего мне не хватает. Вот метод:

 public IList<TransactionStatus> GetBookingStatuses(IList<string> uniqueTransactionRefs)
{
    TransactionStatus[] transactionStatuses = DBRepository.GetStatuses((string[])uniqueTransactionRefs);
    return transactionStatuses;
}
 

И это метод GetStatuses в моем репозитории:

 TransactionStatus[] GetStatuses(string[] uniqueTransactionRefs);
 

Комментарии:

1. Я думаю, вам нужно передать uniqueTransactionRefs методу GetStatuses.

Ответ №1:

IList<string> это интерфейс, который реализует как string array ( string[] ), так и string lists ( List<string> ) . Это означает, что это хороший кандидат для получения нескольких строк независимо от того, какой базовый тип данных используется.

В вашем случае ваш метод GetBookingStatuses получает данные как an IList<string> , но, как вы можете видеть из сообщения об ошибке, фактический тип uniqueTransactionRefs is System.Collections.Generic.List`1[System.String] , т. е. List<string> . Поскольку это допустимо IList<string> , передача данных в метод работает нормально. Но когда вы затем попытаетесь преобразовать его в строковый массив, произойдет сбой, поскольку List<string> он не совместим напрямую с string[] .

Есть два варианта исправления этого:

  • Вы могли List<string> бы явно преобразовать в массив строк, вызвав .ToArray() его. Это создаст новый массив строк с элементами из исходного списка:
     TransactionStatus[] transactionStatuses = DBRepository.GetStatuses(uniqueTransactionRefs.ToArray());
     
  • В зависимости от того, что делает ваш GetStatuses метод, вы также можете изменить его подпись, чтобы она не требовала строкового массива, но также принимала IList<string> . Тогда вы могли бы передать uniqueTransactionRefs из GetBookingStatuses напрямую, без необходимости его преобразования:
     TransactionStatus[] transactionStatuses = DBRepository.GetStatuses(uniqueTransactionRefs);
     
     public TransactionStatus[] GetStatuses(IList<string> uniqueTransactionRefs)
    {
        // …
    }
     

Комментарии:

1. Ха, интересно, я бы подумал, что ToArray() on a List<T> будет оптимизирован для просто возврата базового массива, а не его копирования, но исходный код говорит, что вы правы

2. @CamiloTerevinto Afaik, ToArray() всегда будет создавать новый массив, чтобы вы могли использовать его для быстрого получения безопасной копии массива, которая не может быть изменена исходным источником.