Moq не будет издеваться над невиртивными членами конкретного класса, потому что он не может переопределить код, который выполняется для реализации вашей установки. Вам нужно либо смоделировать интерфейс, который реализует класс.
Если у вас есть это:
public interface IJobOfferController
{
Task<string> UploadCvToAzureStorage(IFormFile file);
}
public class JobOfferController : IJobOfferController
{
public Task<string> UploadCvToAzureStorage(IFormFile file) => throw new NotImplementedException();
}
Тогда вы настроили бы:
public void SetUp()
{
//this is trying to mock the concrete class and will fail
var controller = new Mock<JobOfferController>(context);
controller.Setup(m => m.UploadCvToAzureStorage(It.IsAny<IFormFile>()))
.Returns(Task.FromResult("cv-url"));
//This Mocks the interface and sets up a return value for that interface
var mockController = new Mock<IJobOfferController>();
mockController.Setup(m => m.UploadCvToAzureStorage(It.IsAny<IFormFile>()))
.Returns(Task.FromResult("cv-url"));
}
Кроме того, при использовании насмешливых асинхронных методов вы можете сбросить .FromResult
и просто использовать ReturnsAsync
controller.Setup(m => m.UploadCvToAzureStorage(It.IsAny<IFormFile>()))
.ReturnsAsync("cv-url");
Или
Если у вашего контроллера нет интерфейса, другой вариант - сделать метод вашего контроллера виртуальным, чтобы Moq мог переопределить его с вашей установкой:
public class JobOfferController : IJobOfferController
{
public virtual Task<string> UploadCvToAzureStorage(IFormFile file) => throw new NotImplementedException();
}
//now the setup works
var controller = new Mock<JobOfferController>(context);
controller.Setup(m => m.UploadCvToAzureStorage(It.IsAny<IFormFile>()))
.ReturnsAsync("cv-url");