0

I want to write integration test for my controller which return HttpResponseMessage which have "Content" as string and his content-type "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"

How do me convert this string back instance ExcelFile - libarary gembox?

this controller for example:

        /// <summary>
        /// Save Data
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        [Route(Routes.Download)]
        [ValidateToken]
        [SwaggerResponse(HttpStatusCode.OK, "Xlsx-file with result", typeof(HttpStatusCode))]
        [SwaggerResponse(HttpStatusCode.Unauthorized, "invalid token", typeof(HttpStatusCode))]
        [SwaggerResponse(HttpStatusCode.BadRequest, "Message with description error of validate", typeof(HttpStatusCode))]
        public HttpResponseMessage PostUnloadExcelFile([FromBody]DownloadRequest request)
        {
            var logData = _logMessageBuilder.GetLogMessageDownload(request.Request);

            LogRequest(logData);

            var response = Request.CreateResponse(HttpStatusCode.OK);

            _downloadService.GetExcelFile(request.Data).Save(response, $"{Routes.Download}.xlsx");

            return response;
        }

this example DownloadService

public class DownloadService : BaseDownloadService, IDownloadService
    {
        private const string Sheet = "Work sheet";      
        public ExcelFile GetExcelFile(IList<Event> data)
        {
            var xlsFile = new ExcelFile();
            var workSheet = xlsFile.Worksheets.Add(Sheet);

            SetHeaderWorksSheet(workSheet);

            for (var i = 0; i < data.Count; i++)
            {
                SetCellWorksSheet(data[i], workSheet, i);
            }

            for (var j = 0; j < data.Count + 1; j++)
            {
                SetCellStyleWorksSheet(workSheet, j);
            }
            return xlsFile;
        }
    }

    public class BaseDownloadService
    {

        protected void SetHeaderWorksSheet(ExcelWorksheet workSheet)
        {
            workSheet.Cells[0, ExcelFileIndexes.Item].Value = ConstantsExcelHeader.Item;
            workSheet.Cells[0, ExcelFileIndexes.FirstDate].Value = ConstantsExcelHeader.FirstDate;
            workSheet.Cells[0, ExcelFileIndexes.LastDate].Value = ConstantsExcelHeader.LastDate;

        }

        protected void SetCellWorksSheet(Triplet rowData, ExcelWorksheet workSheet, int i)
        {
            workSheet.Cells[i + 1, ExcelFileIndexes.Item].Value = (i + 1).ToString();
            workSheet.Cells[0, ExcelFileIndexes.FirstDate].Value = rowData.FirstDate;
            workSheet.Cells[0, ExcelFileIndexes.LastDate].Value = rowData.LastDate;

        }

        protected void SetCellStyleWorksSheet(ExcelWorksheet workSheet, int i)
        {
            workSheet.Columns[i].AutoFit();
            workSheet.Cells[0, i].Style
                .FillPattern
                .SetPattern(
                    FillPatternStyle.Solid,
                    SpreadsheetColor.FromName(ColorName.LightGreen),
                    SpreadsheetColor.FromName(ColorName.LightGreen));
        }
    }

this test for example:

        [Theory]
        [MemberData(nameof(DataForTrySaveInExcelFileTesting))]
        public async Task Should_ReturnCode200TrySaveDataInFileExcel(DownloadRequest request)
        {
            // Arrange
            var token = await GetValidTokenAsync();
            // Act
            var response = await ActAsync<DownloadRequest, DataRecord>(request, token, DownloadUrl);

            var excelBytes = Encoding.UTF8.GetBytes(response.Content);
            var excelFile = new ExcelFile();      

            using (MemoryStream stream = new MemoryStream())
            {
                stream.Write(excelBytes, 0, excelBytes.Length);
                stream.Position = 0;
                excelFile = ExcelFile.Load(stream, LoadOptions.XlsxDefault);
            }

            var ws = excelFile.Worksheets.ActiveWorksheet;
            ws.Cells["B2"].Value.ShouldBeEqualTo("1234567890");
        }


This is response for front

this respone for front

Mario Z
  • 4,328
  • 2
  • 24
  • 38
Paul Alexeev
  • 172
  • 1
  • 11
  • You highlighted the header. The actual excel file should be in the body of the http response. – jdweng Mar 25 '19 at 10:16
  • I don't have problem with save excel on client side, I don't get to excelFile back from memoryStream. HttpResponseMessage contain "Content" - this body response. The problem is in converting to the necessary type, I don’t understand whether I'm doing everything correctly or not( – Paul Alexeev Mar 25 '19 at 10:40
  • The file size how much different is the original from the downloaded. If the file is gzip the file size is compressed and will be much smaller. You are using Encoding.UTF8 which will drop characters like 0xFF and then the file will not be usable. You should use BinaryReader or BitConverter class to get bytes. – jdweng Mar 25 '19 at 11:09
  • Ok, how? BitConvert don't get type string only char, do I need to send a string character by character and build an array of bytes? Give an example of working with a string BitConvert. And BinaryReader have three overload, everything receive stream, what I am trying to achieve. I don't have save local file I want to get data from "Content" response as utf-8 string, how do me right convert string as stream whthout losses data for method ExcelFile.Load(stream, LoadOptions.XlsxDefault) – Paul Alexeev Mar 25 '19 at 12:11
  • NEVER, NEVER, NEVER, NEVER, use string on Binary data. It will corrupt the results. – jdweng Mar 25 '19 at 12:13
  • Use following : Stream stream = response.GetResponseStream(); byte[] buffer = new byte[stream.Length]; stream.Read(buffer, 0, (int)stream.Length); – jdweng Mar 25 '19 at 12:18
  • response don't have method GetResponseStream(), response this HttpResponseMessage – Paul Alexeev Mar 25 '19 at 12:30
  • I was using : WebRequest request = WebRequest.Create("URL"); WebResponse response = request.GetResponse(); What are you using? Or HttpWebResponse response = (HttpWebResponse)request.GetResponse(); response.GetResponseStream(); – jdweng Mar 25 '19 at 12:34
  • an example is written in the controller in description question – Paul Alexeev Mar 25 '19 at 12:42
  • I do not have the SwaggerResponse and not sure why it doesn't return a stream method. – jdweng Mar 25 '19 at 13:01

1 Answers1

0

jdweng Thanks you, you made me think and comed good idea.We refused to convert string in stream and we just extended model of response for post of requset and added stream for content an example is shown below.

    protected async Task<TestRequestResponse> PostAsync<TPayload>(string url, TPayload payload, string token = null)
        {
            using (var server = new HttpServer(_config))
            {
                var client = new HttpClient(server);

                var request = new HttpRequestMessage
                {
                    RequestUri = new Uri(url),
                    Method = HttpMethod.Post,
                    Content = new ObjectContent<TPayload>(payload, new JsonMediaTypeFormatter())
                };

                request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                request.Headers.Add("token", token);

                var httpRequest = new HttpRequest(string.Empty, url, string.Empty);
                httpRequest.AddServerVariable("UserHostAddress", "192.168.1.1");
                httpRequest.AddServerVariable("UserAgent", "chrome");
                HttpContext.Current = new HttpContext(httpRequest, new HttpResponse(new StringWriter()));

                using (var response = await client.SendAsync(request))
                {
                    var streamContent = await response.Content.ReadAsStreamAsync();
                    var memoryStream = new MemoryStream();
                    streamContent.CopyTo(memoryStream);
                    memoryStream.Position = 0;
                    var content = await response.Content.ReadAsStringAsync();

                    return new TestRequestResponse
                    {
                        Content = content,
                        StatusCode = response.StatusCode,
                        Message = response.ReasonPhrase,
                        StreamContent = memoryStream
                    };
                }
            }
        }
        [Theory]
        [MemberData(nameof(DataForTrySaveInExcelFileTesting))]
        public async Task Should_ReturnCode200TrySaveDataInFileExcel(DownloadRequest request)
        {
            // Arrange
            var token = await GetValidTokenAsync();

            // Act
            var responseBilling = await ActAsync<DownloadRequest, Record>(request, token, DownloadUrl);
            var excelFile = ExcelFile.Load(response.StreamContent, LoadOptions.XlsxDefault);

            var ws = excelFile.Worksheets.ActiveWorksheet;
            ws.Cells["E2"].Value.ShouldBeEqualTo("11111");
            ws.Cells["Q3"].Value.ShouldBeEqualTo("11111");
            ws.Cells["C4"].Value.ShouldBeEqualTo(11111);
            ws.Cells["F5"].Value.ShouldBeEqualTo("11111");
            ws.Cells["O6"].Value.ShouldBeEqualTo("11111");
            ws.Rows.Count.ShouldBeEqualTo(request.Data.Count + 1);
        }

        public async Task<TestRequsetResponse> ActAsync<TRequest, TItem>(TRequest reuqset = null, string token = null, string url = null) where TRequest : DownloadRequest<Item>
        {
            return await PostAsync(url, request, token);
        }

Paul Alexeev
  • 172
  • 1
  • 11