О-о-о, парень, это был один изумительный.И, честно говоря, я, вероятно, все еще использую бензопилу, когда ножовка, возможно, справилась здесь достаточно хорошо, поэтому я все же буду рад конструктивному отзыву о моем «решении» здесь.
Для того, чтобыAngleSharp, чтобы «сделать свое дело» и вернуть мне статический IDocument
файла, который я сохранил на диск, мне пришлось сделать несколько вещей (некоторые из которых я начал, когда писал эти вопросы, другие я понял сложныйway):
- Обернуть вызов AngleSharp в сервис, который DI может затем внедрить (и я могу фальсифицировать)
- Заставить указанный вызов в сервисе принять параметр
IRequester
, обычнопросто передайте null
и используйте new DefaultHttpRequester()
, когда ноль - Создайте мою собственную реализацию
IRequester
, но сделайте RequestAsync
и SupportsProtocol
virtual
, чтобы Moq мог делать свое дело.Самый простой способ сделать это (в VS Code) - щелкнуть правой кнопкой мыши интерфейс в той же строке, что и ваше поддельное имя класса, и заставить IDE автоматически сгенерировать реализацию.Каждый метод генерирует исключение, но он выполняет контракт. - Выполните двухэтапный танец перед вызовом тестируемого модуля:
- Создайте экземпляр вашего класса-оболочки AngleSharp (истинная реализация,а не интерфейс или макет), затем создайте минимальный макет
IRequester
, макет Адреса, Заголовки и Контент (чтение HTML-файла с диска) и передайте его методу-обертке, возвращая полноценный закон IDocument
HTML-файла на диске. - Создайте макет вашего класса-обертки AngleSharp и смоделируйте метод, сказав ему вернуть
IDocument
из предыдущего шага, а затем предоставьте его для тестируемого модуля.
GAH.Это безумие, и теперь я понимаю, почему этот вопрос является первым результатом в Google:)
В любом случае, для подробностей, вот примерный набросок кода, который я придумал, чтобы решить эту проблему:
Тест:
[Fact]
public async void ItShouldDoSomething() {
using(var autoMock = AutoMock.GetLoose()) {
var mockedWrapper = autoMock.Mock<IAngleSharpWrapper>();
var fakeDocument = await GetFakeDocument();
mockedWrapper.Setup(x => x.OpenUrlAsync(It.IsAny<IRequester>())).ReturnsAsync(fakeDocument);
autoMock.Provide(mockedWrapper);
var sut = autoMock.Create<ClassYouAreTesting>();
var data = await sut.LoadData();
//Perform your assertions here
}
}
Связанные методы окурков и насмешек:
private async Task<IDocument> GetFakeDocument() {
var angleSharpWrapper = new AngleSharpWrapper();
var requesterMock = GetFakeRequesterMock();
return await angleSharpWrapper.OpenUrlAsync("http://askjdkaj", requesterMock.Object);
}
private Mock<FakeRequester> GetFakeRequesterMock() {
var mockResponse = new Mock<IResponse>();
mockResponse.Setup(x => x.Address).Returns(new Url("fakeaddress"));
mockResponse.Setup(x => x.Headers).Returns(new Dictionary<string, string>());
mockResponse.Setup(_ => _.Content).Returns(LoadFakeDocumentFromFile());
var mockFakeRequester = new Mock<FakeRequester>();
mockFakeRequester.Setup(_ => _.RequestAsync(It.IsAny<Request>(), It.IsAny<CancellationToken>())).ReturnsAsync(mockResponse.Object);
mockFakeRequester.Setup(x => x.SupportsProtocol(It.IsAny<string>())).Returns(true);
return mockFakeRequester;
}
private MemoryStream LoadFakeDocumentFromFile() {
//Note: path below is relative to your output directory, so bin/Debug/etc.
using (FileStream fileStream = File.OpenRead(Path.Combine(Directory.GetCurrentDirectory(), "Path/To/Your/LocalFile.html")))
{
MemoryStream memoryStream = new MemoryStream();
memoryStream.SetLength(fileStream.Length);
fileStream.Read(memoryStream.GetBuffer(), 0, (int)fileStream.Length);
return memoryStream;
}
}
* Редактировать: Решил, что я должен также включить метод обертки вокруг AngleSharp, что довольно важно:
public async Task<IDocument> OpenUrlAsync(string url, IRequester defaultRequester)
{
if (defaultRequester == null) {
defaultRequester = new DefaultHttpRequester();
}
var angleSharpConfig = Configuration.Default.WithDefaultLoader().With(defaultRequester);
var angleSharpContext = BrowsingContext.New(angleSharpConfig);
return await angleSharpContext.OpenAsync(url);
}