3

我有一个使用 Asp.Net Core 创建的项目,但是我在对控制器操作的一部分进行单元测试时遇到问题,我使用xUnit.net(2.2.0-beta2-build3300)进行测试和Moq(4.6.25-alpha )用于模拟, FluentAssertions(4.13.0)GenFu(1.1.1)帮助我进行测试,我有一个工作单元类(请注意,我将其缩减为与我的问题相关的内容):

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 和 EF 4.1 模拟 UnitOfWork

但他们都没有帮助,我会很感激任何帮助。

4

1 回答 1

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

于 2016-08-11T18:15:36.390 回答