Nano Hash - криптовалюты, майнинг, программирование

Мок-метод тестируемой системы с Moq

У меня есть следующие три метода в классе CompanyApplication (вместе с перечисленными поддерживающими фабриками и службами):

public ResultSet<CompanyDto> AddCompany(CompanyDto companyDto)
{
    var result = new CompanyDto();
    var company = new Company();
    Mapper.Map(companyDto, company);

    using (ITransaction t = _transactionFactory.Create())
    {
        company = _companyService.Add(company);
        t.Commit();
    }

    Mapper.Map(company, result);
    return new ResultSet<CompanyDto>(1, new[] { result });
}

public ResultSet<CompanyContactDto> AddCompanyContact(CompanyContactDto companyContactDto)
{
    var result = new CompanyContactDto();
    var company = new Company();
    var contact = new CompanyContact();
    Mapper.Map(companyContactDto, contact);

    using (ITransaction t = _transactionFactory.Create())
    {
        var contactCompanies = FindByIdJoin<Company, CompanyDto>(companyContactDto.CompanySK);
        Mapper.Map(contactCompanies.Data.First(), company);
        company.CompanyContacts.Add(contact);
        company = _companyService.Update(company);
        t.Commit();
    }

    Mapper.Map(contact, result);
    return new ResultSet<CompanyContactDto>(1, new[] { result });
}

public ResultSet<T_DtoType> FindByIdJoin<T_DbType, T_DtoType>(long id)
{
    IAbstractRepository<T_DbType> repository = EnsureRepository<T_DbType>();
    T_DbType entity = repository.FindByIdJoin(id);
    return (entity == null ? null : MapResultSetToDto<T_DbType, T_DtoType>(entity));
}

Здесь задействованы другие объекты, поэтому FindByIdJoin был сделан отдельным методом в классе CompanyApplication.

Я настроил класс тестирования с некоторыми макетами и экземпляром класса CompanyApplication:

private Mock<ICompanyRepository> _mockCompanyRepository;
private Mock<ICompanyDomain> _mockCompanyService;
private Mock<ITransactionFactory> _mockTransactionFactory;
private Mock<ITransaction> _mockTransaction;
private CompanyApplication _companyApplication;

[Setup]
public void SetUp()
{
    _mockCompanyRepository = new Mock<ICompanyRepository>(MockBehavior.Strict);
    _mockCompanyService = new Mock<ICompanyDomain>(MockBehavior.Strict);
    _mockTransactionFactory = new Mock<ITransactionFactory>(MockBehavior.Strict);
    _mockTransaction = new Mock<ITransaction>(MockBehavior.Strict);

    _companyApplication = new CompanyApplication(
        _mockCompanyRepository.Object,
        _mockCompanyService.Object,
        _mockTransactionFactory.Object);
}

Я успешно могу протестировать методы FindByIdJoin и AddCompany непосредственно в Moq следующим образом:

[Test]
public void CanFindCompanyByIdJoin()
{
    var data = new Company {ObjectId = 1, Name = "Company1"};
    _mockCompanyRepository.Setup(x => x.FindByIdJoin(It.Is<long>(arg => arg == data.ObjectId)))
        .Returns(data);

    var result = _companyApplication.FindByIdJoin<Company, CompanyDto>(data.ObjectId);

    Assert.AreEqual(data.ObjectId, result.Data.First().ObjectId);
}

[Test]
public void CanAddCompany()
{
    var data = new Company {ObjectId = 1, Name = "Company1"};
    _mockCompanyService.Setup(x => x.Add(It.Is<Company>(arg => arg.ObjectId == data.ObjectId)))
        .Returns(data);

    _mockTransactionFactory.Setup(x => x.Create()).Returns(_mockTransaction.Object);
    _mockTransaction.Setup(x => x.Commit());
    _mockTransaction.Setup(x => x.Dispose());

    var dto = new CompanyDto {ObjectId = 1, Name = "Company1"};
    var result = _companyApplication.AddCompany(dto);

    _mockCompanyService.Verify(t => t.Add(It.IsAny<Company>()));
}

Эти два теста проходят нормально. Однако у меня возникли проблемы с тестом для AddCompanyContact, потому что он вызывает FindByIdJoin как часть своего потока, и это, кажется, мешает.

В частности, есть ли способ имитировать var contactCompanies = FindByIdJoin<Company, CompanyDto>(companyContactDto.CompanySK) в тесте для метода AddCompanyContact?

Спасибо!

30.07.2014

Ответы:


1

Есть две альтернативы, которые я вижу в зависимости от объема работы, которую вы хотите сделать.

  1. Оберните этот вызов в объект и создайте его экземпляр с помощью контейнера IOC. Это тот, который, как мне кажется, потребует наибольших усилий, если вы его еще не используете.
  2. Превратите этот вызов в Func и создайте метод без этого параметра, который выполняет вызов. У этого подхода есть недостаток, заключающийся в том, что вызов top не будет тестироваться, но позволит получить доступ к остальной части метода.

Пример ниже:

public ResultSet<CompanyContactDto> AddCompanyContact(CompanyContactDto companyContactDto)
{
         AddCompanyContact(CompanyContactDto, ()=>
                                              {
                                                 return FindByIdJoin<Company, CompanyDto> companyContactDto.CompanySK); 
                                              }
}

public ResultSet<CompanyContactDto> AddCompanyContact(CompanyContactDto companyContactDto, Func<WhateverTheMethodReturns> findIdReplacement)
{
    var result = new CompanyContactDto();
    var company = new Company();
    var contact = new CompanyContact();
    Mapper.Map(companyContactDto, contact);

    using (ITransaction t = _transactionFactory.Create())
    {
        var contactCompanies = findIdReplacement();
        Mapper.Map(contactCompanies.Data.First(), company);
        company.CompanyContacts.Add(contact);
        company = _companyService.Update(company);
        t.Commit();
    }

    Mapper.Map(contact, result);
    return new ResultSet<CompanyContactDto>(1, new[] { result });
}
30.07.2014

2

Я слишком усложнял проблему... так как AddCompanyContact вызывает FindByIdJoin, все, что мне нужно было сделать, это имитировать тот же интерфейс, который используется в FindByIdJoin.

Усвоенный урок: имитируйте интерфейсы, а не классы.

08.08.2014
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..