I have a method in a WebApi controller for which I want to write unit tests. This is what my controller method looks like:
Controller.cs
public async Task<FileUploadDto> UploadGoalDocument(Guid id) { var file = this.Request?.Form?.Files.FirstOrDefault(); FileUploadDto result = null; if (file == null) { return this.CreateResponse(result); } //logic to store file in db return this.CreateResponse(new FileUploadDto() { Id = document.Id, Name = document.Name, Uri = document.Uri}); }
How can I mock a query object in unit testing? I tried to follow but ran into problems with IFormFileCollection. The following line throws an error:
interface system.argumentexception not found
cc.Setup(x => x.HttpContext.Request.Form.Files).Returns(col.Object);
ControllerTest.cs
public async Task Upload_document_should_upload_document_and_return_dto() { var fileDto = new FileUploadDto { Id = Guid.NewGuid(), Name = "dummy.txt" }; var fileMock = new Mock<IFormFile>(); //Setup mock file using a memory stream using (var ms = new MemoryStream()) { using (var writer = new StreamWriter("dummy.txt")) { writer.WriteLine("Hello World from a Fake File"); writer.Flush(); ms.Position = 0; fileMock.Setup(m => m.OpenReadStream()).Returns(ms); var file = fileMock.Object; this.goalService.Setup(m => m.UploadDocument(Guid.NewGuid(), file, "")) .ReturnsAsync(new Services.DTO.FileUploadDto { Id = fileDto.Id, Name = fileDto.Name }); var cc = new Mock<ControllerContext>(); var col = new Mock<IFormFileCollection>(); col.Setup(x=> x.GetFile("dummy.txt")).Returns(file); cc.Setup(x => x.HttpContext.Request.Form.Files).Returns(col.Object); this.controller.ControllerContext = cc.Object; var result = await this.controller.UploadGoalDocument(Guid.NewGuid()); //Asserts removed for simplicity } } }
Detailed stack trace:
System.RuntimeTypeHandle.VerifyInterfaceIsImplemented(RuntimeTypeHandle handle, RuntimeTypeHandle interfaceHandle) at System.RuntimeType.GetInterfaceMap(Type ifaceType) at Moq.Extensions.IsGetObjectDataVirtual(Type typeToMock) at Moq.Extensions.IsSerializableMockable(Type typeToMock) at Moq.SerializableTypesValueProvider.ProvideDefault(MethodInfo member) at Moq.Mock.GetInitialValue(IDefaultValueProvider valueProvider, Stack`1 mockedTypesStack, PropertyInfo property) at Moq.Mock.SetupAllProperties(Mock mock, Stack`1 mockedTypesStack) at Moq.Mock.<>c__DisplayClass72_0.<SetupAllProperties>b__0() at Moq.PexProtector.Invoke(Action action) at Moq.Mock.SetupAllProperties(Mock mock) at Moq.QueryableMockExtensions.FluentMock[T,TResult](Mock`1 mock, Expression`1 setup) at lambda_method(Closure ) at Moq.Mock.GetInterceptor(Expression fluentExpression, Mock mock) at Moq.Mock.<>c__DisplayClass66_0`2.<SetupGet>b__0() at Moq.PexProtector.Invoke[T](Func`1 function) at Moq.Mock.SetupGet[T,TProperty](Mock`1 mock, Expression`1 expression, Condition condition) at Moq.Mock.<>c__DisplayClass65_0`2.<Setup>b__0() at Moq.PexProtector.Invoke[T](Func`1 function) at Moq.Mock.Setup[T,TResult](Mock`1 mock, Expression`1 expression, Condition condition) at Moq.Mock`1.Setup[TResult](Expression`1 expression)
I think I did not build the test correctly, but a keen eye can point me in the right direction.