Moq ожидается:Но было: не исключение брошено - PullRequest
0 голосов
/ 13 ноября 2018

У меня есть функция модульного теста, которая сработала. Когда я включил ILogger и Moq framework, исключений больше не было. Смотрите последний тест ниже. При пошаговой отладке модульного теста я знаю, что выдается исключение. Поэтому не уверен, почему он не отображается в Nunit и не вызывает ошибку.

Ошибка:

Message:   Expected: <System.ArgumentException>  But was:  no exception thrown



using System;
using ElectronicsStore.Models;
using Microsoft.Extensions.Logging;

namespace ElectronicsStore.Service
{
    public class ParseVendorSupply
    {
        private readonly ILogger _logger;

        public ParseVendorSupply(ILogger logger)
        {
            _logger = logger;
        }

        public VendorSupply FromCsv(string csvLine)
        {
            VendorSupply vendorsupply = new VendorSupply();

            try
            {
                string[] values = csvLine.Split(',');
                if (values.Length > 3)
                {
                    throw new System.ArgumentException("Too much data");
                }

                vendorsupply.VendorId = Convert.ToInt16(values[0]);
                vendorsupply.ProductId = Convert.ToInt16(values[1]);
                vendorsupply.Quantity = Convert.ToInt16(values[2]);
            }
            catch (Exception)
            {
                _logger.LogInformation("An exception was thrown attempting");
            }
            return vendorsupply;
        }       
    }
}

Тест NUnit:

public class ParseVendorSupplyNunit
{

    ILogger logger;

    // This Works
    [Test]
    public void FromCsv_ParseCorrectly()
    {
        var logger = new Mock<ILogger>();
        var parseVendorSupply = new ParseVendorSupply(logger.Object);
        string csvLineTest = "5,8,3";
        VendorSupply vendorsupply = parseVendorSupply.FromCsv(csvLineTest);
        Assert.AreEqual(5, vendorsupply.VendorId);
        Assert.AreEqual(8, vendorsupply.ProductId);
        Assert.AreEqual(3, vendorsupply.Quantity);
    }

    // This does not work anymore,after adding ILogger and Moq
    [Test]
    public void FromCsv_ParseCorrectly_Extradata()
    {
        var logger = new Mock<ILogger>();
        var parseVendorSupply = new ParseVendorSupply(logger.Object);

        string csvLineTest = "5,8,3,9,5";

        Assert.That(() => parseVendorSupply.FromCsv(csvLineTest), Throws.ArgumentException);
    }

Message:   Expected: <System.ArgumentException>  But was:  no exception thrown

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

(Это не относится к Moq.) Я думаю, вы знаете, что вы добавили в свой код блок try...catch, который поглощает исключение;но вы не понимаете, почему утверждение о том, что выбрано определенное исключение, сейчас не выполняется.В конце концов, вы все еще выбрасываете исключение, поэтому вам интересно, почему NUnit не замечает.

NUnit не работает, наблюдая за тем, что делает ваш код во время его выполнения.Единственный способ определить, было ли выброшено исключение, состоит в том, что это исключение всплывает в вызывающем коде (вызывающий код - это утверждение, что в методе test создается исключение).

Вы можете думать о своем утверждении, что ArgumentException был брошен как catch(ArgumentException).И поскольку ваш новый код поглощает исключение, утверждение в тесте никогда не будет видеть исключение, поэтому утверждение не выполняется.

Как примечание, касающееся дизайнапосмотрите, как ведет себя ваш код, если выбрасывается это исключение.Вызывающий просто возвращает объект (как если бы он работал).Таким образом, вызывающий код не поймет, что что-то пошло не так (я бы сказал, что это плохой дизайн).

Вы можете использовать Moq, чтобы убедиться, что метод LogInformation был вызван один раз;но это могло быть вызвано другим исключением.

Стоит также отметить, что интересным вариантом является вызов LogInformation для чего-то, что явно остановит работу программы.LogInformation для вещей, которые могут представлять интерес.Рассмотрите возможность использования другого метода на регистраторе, я бы предложил LogError или еще хуже.

0 голосов
/ 13 ноября 2018

Ваш код генерирует исключение внутри блока try-catch. Поэтому ваше выброшенное исключение не покинет область действия функции. В результате этого модульный тест не пройден.

        try
        {
            string[] values = csvLine.Split(',');
            if (values.Length > 3)
            {
                throw new System.ArgumentException("Too much data");
            }

            vendorsupply.VendorId = Convert.ToInt16(values[0]);
            vendorsupply.ProductId = Convert.ToInt16(values[1]);
            vendorsupply.Quantity = Convert.ToInt16(values[2]);
        }
        catch (Exception)
        {
            _logger.LogInformation("An exception was thrown attempting");
        }

Вы можете перебросить ArgumentException, см. Ссылку stackoverflow для получения дальнейших указаний. Но это плохая идея использовать исключение для «связи» внутри метода. Таким образом, вы можете просто переместить проверку параметров, чтобы она находилась вне блока try-catch.

Надеюсь, что поможет

...