Простой `Assert.Ошибка IsAssignableFrom`

#c# #unit-testing #nunit

#c# #модульное тестирование #nunit

Вопрос:

Почему этот простой оператор assert завершается ошибкой? Из того, что я прочитал, я должен быть . К сожалению, поскольку функциональность настолько проста, там не так много информации.

 public interface IDummy{}
public class Dummy : IDummy {}

Assert.IsAssignableFrom<IDummy>(new Dummy());
  

Выполнение этого теста дает

 Expected: assignable from <Application.Tests.ViewModels.IDummy>
  But was:  <Application.Tests.ViewModels.Dummy>
  

Я пытался поменять местами интерфейс и объекты, но безрезультатно.

Ответ №1:

IsAssignableFrom работает в обратном направлении от того, что вы ожидаете. Он спрашивает: Is (значение) Присваивается из IDummy. Или: «Можно ли присвоить (значение)?»

Из XML-документа: /// Утверждает, что объекту может быть присвоено значение заданного типа.

Вы, вероятно, хотите Assert.IsInstanceOfType()

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

1. Ах, это работает. Спасибо. В чем тогда цель IsAssignableFrom ?

2. @gsco, смотрите мой ответ ниже

Ответ №2:

В интересах тех, кто попадает сюда через Google (или Bing :-))

Assert.IsAssignableFrom<T>(object actual) предназначено для проверки того, может ли проверяемый объект быть заменен типом T. Фактически, это означает, что утверждение проверяет связь «is-a» между проверяемым объектом и типом T.

Давайте посмотрим некоторый код (намеренно упрощенный):

 // The Base class
public class Employee
{
    public int EmployeeId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfJoining { get; set; }
}

// The derived class
public class Manager : Employee
{
    public IList<Employee> EmployeesReporting { get; set; }
}
  

Теперь утверждение:

 // NOTE: using Assert = NUnit.Framework.Assert;
[TestMethod]
public void Test_IsAssignableFrom()
{
    var employee = new Employee();

    // Manager is-a Employee, so the below is true
    Assert.IsAssignableFrom<Manager>(employee);    
}
  

В то время как IsInstanceOf<T>(object actual) предназначен для проверки того, является ли тестируемый объект (как следует из названия) экземпляром типа T — проще говоря, является ли «actual» типом T или типом, производным от T

 [TestMethod]
public void Test_IsAssignableFrom()
{
    var manager = new Manager();

    // Manager derives from Employee so the below is true
    Assert.IsInstanceOf<Employee>(manager);   
}
  

Редактировать
Оказывается, эти утверждения работают так же, как и Type .IsAssignableFrom и введите.isInstanceOf методы в системе.Тип

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

1. Итак, в курсе PluralSight Марка Симана он использует xUnit. Существует класс, определенный как public class SimpleWebToken : IEnumerable<Claim> {...} . Затем в своем тесте xUnit он имеет Assert.IsAssignableFrom<IEnumerable<Claim>>(sut) (где sut — экземпляр SimpleWebToken ). И этот тест пройден! Но, судя по всему, это должно завершиться неудачей. При использовании точно такого же утверждения с NUnit тест завершается с ошибкой. И запуск var good = SimpleWebToken.GetType().IsAssignableFrom(typeof(IEnumerable<Claim>)); // good = false дает мне ожидаемый false результат. Хммм, я теряю уверенность в тестировании фреймворков.

2. Не обращайте на это внимания. xUnit делает что-то необычное, но классное, потому что оно имитирует то, как вы используете System.Type.IsAssignableFrom(Type) метод в BCL. С другой стороны, NUnit имеет методы ограничения IsAssignableFrom и IsAssignableTo , которые отличаются от BCL. Итак, при использовании отражения вы бы использовали IsAssignableFrom , но при написании утверждения в NUnit вы бы использовали Is.AssignableTo<TType>() ограничение. Сбивает с толку.

3. @fourpastmidnight В эти дни я предпочитаю использовать замечательную потрясающую библиотеку утверждений, где я могу упростить утверждение как someInstance.ShouldBeOfType<TExtpected>