2016-08-11 96 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)来帮助我与我的测试中,我有工作类的单位(请注意,我把它删减到什么有关我的问题):Moq的Stubed工作方法不会返回预期的整数

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方法(在这种情况下,10)返回一个大于0的整数,国米的,如果子句和测试,以查看是否返回正确的观点,我的测试类:

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

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财产起订量不支持设置的“链接”。

  2. 此外,你需要使用It.IsAny<>()而不是A.New<>()

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

    这是说 “匹配在传递的任何Contact”。当您使用A.New<>()时,您的意思是“匹配Contact我刚刚创建的实例与A.New<>()。实际上,由于您没有保存或使用返回值A.New<>(),因此这绝不会匹配任何内容。