Используйте Moq для выполнения модульного тестирования службы экспорта данных - PullRequest
0 голосов
/ 18 марта 2019

У меня есть служба для экспорта в виде CSV-файла, который находится внутри видеомодели в приложении WPF:

 public void ExportToExcel()
    {

        DataTable tblFiltered = _currentTable.AsEnumerable()
                          .Where(r => r.Field<string>("Type") == ExportGridGroup)
                          .CopyToDataTable();

        StringBuilder sb = new StringBuilder();
        IEnumerable<string> columnNames = tblFiltered.Columns.Cast<DataColumn>().
                                          Select(column => column.ColumnName);
        sb.AppendLine(string.Join(",", columnNames));

        foreach (DataRow row in tblFiltered.Rows)
        {
            IEnumerable<string> fields = row.ItemArray.Select(field => "\"" + field.ToString() + "\"");
            sb.AppendLine(string.Join(",", fields));
        }

        String result = sb.ToString();
        try
        {
            StreamWriter sw = new StreamWriter("export.csv");
            sw.WriteLine(result);
            sw.Close();
            Process.Start("export.csv");
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

Итак, на основании этого я создал для него метод тестирования, но еще не закончил;

 [TestMethod()]
    public void ExportToExcelTest()
    {
        //Step 1: Creating a mock table with columns
        DataTable testtable = new DataTable();
        DataRow mydatarow;
        mydatarow = testtable.NewRow();
        //Step 2: Adding the row 
        mydatarow["ColumnA"] = "12345";
        mydatarow["ColumnB"] = "test";

        testtable.Rows.Add(mydatarow);

        StringBuilder sb = new StringBuilder();
        IEnumerable<string> columnNames = testtable.Columns.Cast<DataColumn>().
                                          Select(column => column.ColumnName);
        sb.AppendLine(string.Join(",", columnNames));

        foreach (DataRow row in testtable.Rows)
        {
            IEnumerable<string> fields = row.ItemArray.Select(field => "\"" + field.ToString() + "\"");
            sb.AppendLine(string.Join(",", fields));
        }

        String result = sb.ToString();
        StreamWriter sw = new StreamWriter("export.csv");
        sw.WriteLine(result);
        sw.Close();
        Process.Start("export.csv");          
        Assert.Fail();
    }

Я немного сбит с толку, потому что в методе тестирования я почти пишу точно такой же код в проекте ..... Могу ли я дать несколько советов о том, как написать этот модульный тест, и любые подробные ссылки на WPF/ C # Unit Testing с использованием Moq для меня, чтобы начать с?

1 Ответ

2 голосов
/ 18 марта 2019

Рассмотрите возможность извлечения кода из вашего блока try в другую службу

public interface ICsvWriter
{
    void WriteOutput(string text);
}

и передайте его как зависимость от конструктора службы экспорта

public Service(ICsvWriter csvWriter)
{
    this.csvWriter = csvWriter;
}

Затем вы можете написатьтест, подобный этому, чтобы убедиться, что он действительно выводит то, что вы ожидаете.

[TestMethod]
public void TestMethod1()
{
    var csvWriter= new Mock<ICsvWriter>();
    var service = new Service(csvWriter.Object);
    string exportedText = string.Empty;

    // set up your mock so that whatatever string you pass in
    // gets passed to your exportedText variable.
    csvWriter.Setup(s => s.WriteOutput(It.IsAny<string>())).Callback<string>(s => exportedText = s);

    var testtable = new DataTable();
    // .... add test data

    // set the table on the view model
    service.SetData(testtable);

    // call the export method.
    service.ExportToExcel();

    // check that the result matches your expectation
    Assert.AreEqual("the text you expect to be written", exportedText);
}

Обновление

Вы можете улучшить свой тест, используя параметризованное тестирование для тестирования различныхсценарии с тем же методом тестирования.

Если вы используете MSTest, есть атрибут DataRow.Для xUnit это называется InlineData или для NUnit это называется TestCase.Все они работают так:

[TestMethod]
[DataRow("12345", "test", "expected output text")]
[DataRow("abcde", "123", "expected output text")]
[DataRow("fghij", "456", "expected output text")]
public void TestMethod1(string columnA, string columnB, string expectedOutput)
{
    // ....
}

Обновление

Вы также можете улучшить тестируемость вашего метода экспорта, передав в качестве параметра DataTable.Затем вы можете проверить его, не имея публичного свойства для установки данных.

public void ExportToExcel(DataTable currentTable)
{
    DataTable tblFiltered = currentTable.AsEnumerable()
                          .Where(r => r.Field<string>("Type") == ExportGridGroup)
                          .CopyToDataTable();

    // ... 
}

Другое обновление

На самом деле, использование обратного вызова не требуется.Извините, я должен был предложить сделать это более чистым способом:

Настроить так:

csvWriter.Setup(s => s.WriteOutput(It.IsAny<string>()));

Затем проверить это следующим образом:

csvWriter.Verify(s => s.WriteOutput("expected text"), Times.Once);
...