2015-09-04 5 views
1

Оказывается, что следующий код не ведет себя, как я бы ожидать:FakeItEasy - проблемы с новым модификатором

using FakeItEasy; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 

[TestClass] 
public class UnitTest1 
{ 
    [TestMethod] 
    public void TestMethod1() 
    { 
     var derived = A.Fake<IDerived>(); 
     A.CallTo(() => derived.Dependency).Returns(null); 

     IBase baseObj = derived; 
     Assert.IsNull(baseObj.Dependency); //Fails 
    } 
} 

public interface IDerived : IBase 
{ 
    new IDependency Dependency { get; } 
} 

public interface IBase 
{ 
    IDependency Dependency { get; } 
} 

public interface IDependency 
{ 
} 

Вместо возвращения пустой, поддельный легко возвращает фальшивый экземпляр IDependency. Возможно, по дизайну? Во всяком случае, как я могу обойти эту проблему и убедиться, что baseObj.Dependency возвращает то, что было настроено?

+0

Обратите внимание, что этот вопрос снова поднят как проблема 533 GitHub, [интерфейс Faking, который содержит свойство с новым модификатором и литье в базовый интерфейс, будет отвлекать результаты] (https://github.com/FakeItEasy/FakeItEasy/issues/ 533). Я ожидал, что большинство обсуждений состоится там сейчас. –

+0

Хорошо, моя точка публикации на github в то время была скорее подачей ошибки. Хотя теперь мне кажется, что это запрос функции. –

ответ

4

Это нормальное поведение. В настоящее время у IDerived есть два члена. Один унаследован от IBase и один, определенный в IDerived.

В вашем методе тестирования вы используете FakeItEasy, чтобы установить значение параметра в IDerived.

Член от IBase не был установлен. Таким образом, он получает значение по умолчанию, которое дает FakeItEasy, которое является издевательством.

Если вы хотите установить его, используйте следующий код:

IDerived derived = A.Fake<IDerived>(); 

IBase baseObj = derived; 

A.CallTo(() => baseObj.Dependency).Returns(null); 

Assert.IsNull(baseObj.Dependency); //No error here 

В этом коде, мы устанавливаем другой член IDerived, который является зависимость определяется в базовом интерфейсе.

+0

Я немного раскололся. С одной стороны, я думаю, «это должно имитировать [этот код] (http://pastebin.com/qzRwC5NW)». С другой стороны, возможно, FakeItEasy должна сохранять свою гибкость. –

+0

В классе Derived в вашем ссылочном коде у вас есть автоматическое свойство. Установщик этого свойства ** не является частью ** какого-либо интерфейса. Под капотом установщик сохранит значение в некотором скрытом поле. Однако получатель этого свойства фактически реализует два свойства интерфейса: IBase.Dependency и IDerived.Dependency. Поэтому, когда ваш потребительский код вызывает какой-либо из этих свойств, они будут обслуживаться одним и тем же получателем, который читает из скрытого поля. –

+0

Я не уверен, почему упоминание о том, что это автоматическое свойство имеет значение, поскольку поведение одинаково для свойства с полем поддержки. Дело в том, что для конкретной реализации ссылка одинакова независимо от того, к какому типу она применяется. Если производный класс реализует 50 интерфейсов, обладающих свойством с тем же именем, приведение к любому из них и обращение к этому свойству приведет к тому же элементу vtable для свойства, верно? «FakeItEasy» не подражает этому поведению, насколько мне известно. И, кроме того, я не понимаю, почему я думаю, что это может привести к некоторым проблемам. –

Смежные вопросы