2016-11-29 14 views
5

Tôi có một phương pháp trong bộ điều khiển WebApi mà tôi muốn viết các bài kiểm tra đơn vị. Đây là cách thức điều khiển của tôi trông:Tải tập tin thử nghiệm đơn vị với Moq .net Core

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}); 
    } 

Làm thế nào tôi có thể thử các đối tượng yêu cầu trong kiểm tra đơn vị? Tôi đã thử làm theo nhưng gặp sự cố với IFormFileCollection. Dòng sau ném lỗi: không tìm thấy

giao diện System.ArgumentException

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 
      } 
     } 
    } 

Chi tiết 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) 

Tôi nghĩ rằng tôi đã không xây dựng các bài kiểm tra đúng cách, nhưng một con mắt quan tâm có thể chỉ cho tôi đi đúng hướng.

+0

'chạy vào vấn đề với IFormFileCollection. 'Có vấn đề gì? làm rõ – Nkosi

+0

@Nkosi Xem cập nhật của tôi để biết thêm chi tiết. Tôi hy vọng tôi đã giải thích nó tốt hơn. – user869375

+0

Không nên bạn moq ra HttpContext, Yêu cầu, hình thức và tập tin và thiết lập chúng để moqHttpContext.Returns (moqRequest.Object) moqRequest.Returns (moqForms.Object) và moqForms.Returns (moq.Files)? –

Trả lời

3

Đối với bất cứ ai phải đối mặt với vấn đề tương tự, đây là những gì tôi đã làm để có được nó làm việc -

ControllerTest.cs

[TestMethod] 
    public async Task Upload_document_should_upload_document_and_return_dto() 
    { 
     var goalId = Guid.NewGuid(); 
     var file = new Services.DTO.FileUploadDto { Id = goalId, Name = "dummy.txt", Uri = "path/to/file" }; 

     this.goalService.Setup(m => m.UploadDocument(It.IsAny<Guid>(), It.IsAny<IFormFile>(), It.IsAny<string>())).ReturnsAsync(file); 

     //**This is the interesting bit** 
     this.controller.ControllerContext = this.RequestWithFile(); 
     var result = await controller.UploadGoalDocument(goalId); 

     Assert.IsNotNull(result); 
     Assert.AreEqual(file.Id, result.Data.Id); 
     Assert.AreEqual(file.Name, result.Data.Name); 
     Assert.AreEqual(file.Uri, result.Data.Uri); 
    } 

    //Add the file in the underlying request object. 
    private ControllerContext RequestWithFile() 
    { 
     var httpContext = new DefaultHttpContext(); 
     httpContext.Request.Headers.Add("Content-Type", "multipart/form-data"); 
     var file = new FormFile(new MemoryStream(Encoding.UTF8.GetBytes("This is a dummy file")), 0, 0, "Data", "dummy.txt"); 
     httpContext.Request.Form = new FormCollection(new Dictionary<string, StringValues>(), new FormFileCollection { file }); 
     var actx = new ActionContext(httpContext, new RouteData(), new ControllerActionDescriptor()); 
     return new ControllerContext(actx); 
    } 
+0

Mã tuyệt vời. Không cần cho một mô hình khi triển khai công khai và rất đơn giản! –

Các vấn đề liên quan