Вызывает насмешливый конструктор в 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 ..
}