Moq - как проверить вызов метода, какой параметр был очищен (список) - PullRequest
2 голосов
/ 14 февраля 2012

У меня есть следующий код, и мне нужна помощь, чтобы написать для него модульный тест.Я использую библиотеку Moq.

Вот сделка.У меня есть бизнес-класс с зависимостью от хранилища (интерфейса), поэтому я могу использовать его для сохранения своих сущностей в базе данных.Моя сущность - это в основном список строк.Метод AddAndSave из MyBusinessClass получает значение, которое он получает в качестве параметров, помещает его в список и вызывает метод Save из IRepository.Затем я очищаю список моей сущности.Приведенный ниже код демонстрирует этот пример (я упростил его, поэтому я могу объяснить его здесь).

Также есть модульный тест.

using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

namespace TestesGerais
{
    public class MyEntity
    {
        public MyEntity()
        {
            MyList = new List<string>();
        }
        public List<string> MyList { get; set; }
    }

    public interface IRepository
    {
        void Save(MyEntity entity);
    }

    public class MyBusinessClass
    {
        public IRepository Repository { get; set; }
        private MyEntity _entity = new MyEntity();
        public void AddAndSave(string info)
        {
            _entity.MyList.Add(info);
            Repository.Save(_entity);
            _entity.MyList.Clear();  // for some reason I need to clear it
        }
    }

    [TestClass]
    public class UnitTest10
    {
        [TestMethod]
        public void TestMethod1()
        {
            var mock = new Mock<IRepository>();
            MyBusinessClass b = new MyBusinessClass() { Repository = mock.Object };
            b.AddAndSave("xpto");
            mock.Verify(m => m.Save(It.Is<MyEntity>(x => x.MyList[0] == "xpto")), Times.Exactly(1));
        }
    }
}

Мой модуль проверяет, еслиМетод Save IRepository был вызван с его параметром (сущностью), имеющим один элемент в списке и имеющим значение «xpto» в этом элементе.

Когда я запускаю этот тест, он становится красным с сообщением об ошибке "Метод тестирования TestesGerais.UnitTest10.TestMethod1 вызвал исключение: System.ArgumentOutOfRangeException: индекс вышел за пределы диапазона. Должен быть неотрицательным и меньше размера коллекции. Имя параметра: index ".

Хорошо, этовызвано списком, который был очищен.Если я прокомментирую строку «_entity.MyList.Clear ();», все пойдет хорошо.

Мой вопрос: как я могу проверить это, не комментируя строку «Очистить» в моем бизнес-классе и убедившись, чточто метод моего репозитория называется передачей определенного значения (сущности с одним элементом со значением "xpto")?

Спасибо

Ответы [ 2 ]

1 голос
/ 14 февраля 2012

Я изменил свой юнит-тест, используя функцию обратного вызова в Moq. Таким образом, я могу настроить макет так, чтобы при вызове AddAndSave полученный параметр сохранялся в переменную из моего модульного теста, и я могу утверждать его позже.

    [TestMethod]
    public void TestMethod1()
    {
        var mock = new Mock<IRepository>();
        string result = string.Empty;
        mock.Setup(m => m.Save(It.IsAny<MyEntity>())).Callback((MyEntity e) => { result = e.MyList[0]; });
        MyBusinessClass b = new MyBusinessClass() { Repository = mock.Object };
        b.AddAndSave("xpto");
        Assert.AreEqual(result, "xpto");
    }
0 голосов
/ 14 февраля 2012

Вы можете немного разделить свой метод.«AddAndSave» - это еще не все.Затем вы можете просто протестировать поведение бита добавления и сохранения в отдельности.

...