Метод Stubed Unit of Work с Moq не возвращает ожидаемое целое число

У меня есть проект, созданный с использованием Asp.Net Core, но у меня проблема с модульным тестированием одной части действия моего контроллера, я использую xUnit.net(2.2.0-beta2-build3300) для тестирования и Moq(4.6.25-alpha) для насмешек, а также для FluentAssertions(4.13.0) и GenFu(1.1.1), чтобы помочь мне с моими тестами, у меня есть класс Unit of Work (обратите внимание, что я сократил его до того, что имеет отношение к моему вопросу):

public class UnitOfWork : IUnitOfWork
{

    private readonly WebForDbContext _context;

    public UnitOfWork(WebForDbContext context)
    {
        _context = context;
    }

     private IContactRepository _contactRepository;

     public IContactRepository ContactRepository
    {
        get
        {

            if (this._contactRepository == null)
            {
                this._contactRepository = new ContactRepository(_context);
            }
            return _contactRepository;
        }
    }
}

В моем ContactRepository у меня есть:

public class ContactRepository:IContactRepository
{
    private WebForDbContext _context;

    public ContactRepository(WebForDbContext context)
    {
        _context = context;
    }

    public Task<int> AddNewContactAsync(Contact contact)
    {
        _context.Contacts.Add(contact);
        return _context.SaveChangesAsync();
    }
}

Я ввожу Единицу работы в мой контроллер, мои действия:

 [HttpPost]
 [ValidateAntiForgeryToken]
 public async Task<IActionResult> Create(ContactViewModel contactViewModel)
  {
       var contactWioutJavascript = _webForMapper.ContactViewModelToContact(contactViewModel);

       int addContactResultWioutJavascript = await _uw.ContactRepository.AddNewContactAsync(contactWioutJavascript);

        if (addContactResultWioutJavascript > 0)
        {
            return View("Success");
        }
  }

Что я хочу сделать, это заглушить мой AddNewContactAsync метод для возврата целого числа больше 0 (в данном случае 10), для вставки в предложение if и проверки, чтобы увидеть, возвращено ли правильное представление, мой тестовый класс:

public class ContactControllerTests
{

 private Mock<IUnitOfWork> _uw;
 private Mock<IWebForMapper> _webForMapper;

    public ContactControllerTests()
    {
        _uw = new Mock<IUnitOfWork>();

        _webForMapper = new Mock<IWebForMapper>();
    }

   [Fact]
    public async Task Create_SouldReturnSuccessView_IfNewContactAdded()
    {
        var contactViewModel = A.New<ContactViewModel>();

        _webForMapper.Setup(s => s.ContactViewModelToContact(contactViewModel)).Returns(A.New<Contact>());

        _uw.Setup(u => u.ContactRepository.AddNewContactAsync(A.New<Contact>())).ReturnsAsync(10);

        var sut = new ContactController(_uw.Object, _webForMapper.Object);

        var result = (ViewResult)await sut.Create(contactViewModel);

        result.ViewName.Should().Be("Success");
    }
 }

Но метод AddNewContactAsync возвращает 0, и мой тест не входит в условие if, которое приводит к return View("Success")Я знаю, что проблема не связана с ReturnAsync потому что я использовал его с другими асинхронными методами, и он работает, также _webForMapper правильно задан и сопоставить модель представления с моей моделью домена и contactWioutJavascript заполнен значением, но когда я отлаживаю тест и достигаю addContactResultWioutJavascript строка, она возвращает 0, независимо от того, что я делаю.

Вещи, которые я делал, но не работал:

Я высмеял ContactRepository и попытался заглушить это:

_contactRepository.Setup(c => c.AddNewContactAsync(A.New<Contact>())).ReturnsAsync(10);

_uw.SetupGet<IContactRepository>(u => u.ContactRepository).Returns(_contactRepository.Object);

Я также нашел другие вопросы:

Moq Unit of Work

Как сделать простую функцию добавления, которая использует Единицу работы и Шаблон репозитория

Mocking UnitOfWork с Moq и EF 4.1

Но никто из них не помог, я был бы признателен за любую помощь.

1 ответ

Решение

Вы почти там. Две вещи:

  1. Вам нужно настроить ContactRepository свойство как Moq не поддерживает "цепочку" настроек.

  2. Также вам нужно использовать It.IsAny<>() вместо A.New<>():

    _contactRepository.Setup(c => c.AddNewContactAsync(It.IsAny<Contact>())).ReturnsAsync(10);
    

    Это говорит "соответствует любому Contact что передается в ". Когда вы использовали A.New<>()Вы говорили "соответствовать Contact экземпляр, который я только что создал с A.New<>(), По сути, это никогда не будет соответствовать ничего, так как вы не сохранили или не использовали возвращаемое значение A.New<>(),

Другие вопросы по тегам