2016-08-11 7 views
3

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

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 в данном случае), в том КРПЕ пункт, и тест, чтобы увидеть, если правильный вид возвращается, мой тестовый класс:

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, и мой тест не входит, если условие, которое приводит к return View("Success"), я знаю, что проблема не связана с ReturnAsync, потому что я использовал ее с другими методами async, и она работает, также _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

how to moq simple add function that uses Unit of Work and Repository Pattern

Mocking UnitOfWork with Moq and EF 4.1

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

+1

На стороне примечания по используемой терминологии, чтобы избежать путаницы: то, что вы там делаете, не стучит, его издевательски (отсюда и название этого типа фреймворков). Stubbing - это тестовая реализация интерфейса или базового класса, что обычно означает, что вам нужно реализовать все методы/свойства интерфейса, где, как в макете, вы можете настраивать/измакать только те, которые вам нужны в вашем тесте. – Tseng

+0

@Tseng Согласно [this] (http://stackoverflow.com/a/27151309/1650277), _Stub - переопределить методы для возврата жестко заданных значений, также называемых state-based_, и я думаю, что это то, что я сделал с методом AddNewContactAsync, но я все еще может быть неправильным. –

ответ

3

Вы почти находитесь. Две вещи:

  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<>().