Вызывает насмешливый конструктор в Justmock для UrlHelper

В justmock мы можем вернуть имитированные экземпляры вместо реальных, организовав вызов конструктора как

Mock.Arragne(()=>new MyClass(Arg.IsAny<string>())).IgnoreInstance().Returns(Mock.Create<MyClass>());

но когда я попробовал то же самое с UrlHelper класс, а не фиктивный тип, фактический тип становится экземпляром. Кто-нибудь может сказать, есть ли ошибка в этом:

UrlModel класс

    public class UrlModel
    {
        private UrlHelper url;
        public UrlModel()
        {
           url = new UrlHelper(HttpContext.Current.Request.RequestContext);
        }
    }

Метод испытания:

public void UrlTest()
{
   Mock.Arrange(() => HttpContext.Current.Request.RequestContext).Returns(Mock.Create<RequestContext>());

    var mockedUrl = Mock.Create<UrlHelper>();

    Mock.Arrange(() => new UrlHelper(Arg.IsAny<RequestContext>()))
        .IgnoreArguments()
        .IgnoreInstance()
        .Returns(mockedUrl);

    //Here url will have actual instance instead of mocked instance
    var model = new UrlModel();

    //Assert is ommitted for bravity .. 
}

3 ответа

Вы можете использовать Typemock для тестирования вашего кода без добавления новых интерфейсов, подделав RequestContext и изменение свойства свойства:

[TestMethod,Isolated]
public void UrlTest()
{
    //Arrange 
    var fakeRequest = Isolate.Fake.Instance<RequestContext>();
    Isolate.WhenCalled(() => HttpContext.Current.Request.RequestContext).WillReturn(fakeRequest);

    //Act
    var res = new UrlModel();
    //getting the private field so it can be asserted
    var privateField = Isolate.NonPublic.InstanceField(res, "url").Value as UrlHelper;

    //Assert
    Assert.AreEqual(fakeRequest, privateField.RequestContext);
}

Единственная причина, почему насмешка конструктора в этом случае не сработала бы, состоит в том, что UrlModel класс был частью тестового класса - сам код в тестовых классах сам по себе не является надёжным.

Еще одна вещь, которая приходит на ум, это то, что вы могли быть введены в заблуждение отладчиком. Когда вы создаете макет неабстрактного типа с запущенным профилировщиком, сам экземпляр имеет тот же тип, что и макетированный тип - это не производный тип, скажем, UrlHelperMock, как и в случае, когда профилировщик не работает. Можете ли вы подтвердить использование отладчиков Make Object ID функция, что макет экземпляра и экземпляр вернулся из new действительно не то же самое?

Вы пришли к выводу, что new выражение насмешки не сработало, потому что ваши договоренности UrlHelper не работал или это было что-то еще?

Вы вручную создаете экземпляр UrlHelper в конструкторе UrlModel, UrlModel теперь тесно связан с UrlHelper (новый клей). Создайте абстракцию зависимостей, которую вы можете использовать для более слабосвязанной модели и улучшенной способности к моделированию

public interface IUrlHelperAccessor {
    UrlHelper UrlHelper { get; }
}

и ввести это в UrlModel

public class UrlModel {
    private UrlHelper url;
    public UrlModel(IUrlHelperAccessor accessor) {
       url = accessor.UrlHelper;
    }
    //...other code
}

Теперь вы устраиваете тест соответственно

public void UrlTest() {
    Mock.Arrange(() => HttpContext.Current.Request.RequestContext)
        .Returns(Mock.Create<RequestContext>());

    var mockedUrl = Mock.Create<UrlHelper>(Constructor.Mock);
    var mockedAccessor = Mock.Create<IUrlHelperAccessor>();

    Mock.Arrange(() => mockedAccessor.UrlHelper).Returns(mockedUrl);

    //Here url will have actual instance instead of mocked instance
    var model = new UrlModel(mockedAccessor);

    //Assert is omitted for brevity .. 

}
Другие вопросы по тегам