Модульное тестирование репозитория - как бороться с сервисами mocking и dbcontext в. Net Core? - PullRequest
0 голосов
/ 16 января 2020

Я пытаюсь выполнить модульное тестирование относительно простого репозитория, но мне было трудно определить лучший подход для работы со службами и контекстами базы данных, для которых требуется создание репозитория.

Репозиторий имеет один метод publi c, который возвращает объект Member:

public class MemberRepository : IMemberRepository
{
    private OServiceContext _openService;
    private OpenDbContext _openDbContext;

    public MemberRepository(OServiceContext openService, OpenDbContext openDbContext)
    {
        _openService = openService;
        _openDbContext = openDbContext;
    }

    public async Task<Member> GetMember(int policyMemberId, int policyActivityId)
    {
        Member member = null;

        var members = await _openDbContext.PolicyMembers
            .Include(c => c.Contact)
            .SingleOrDefaultAsync(x => x.PolicyActivityKey == policyActivityId && x.PolicyMemberKey == policyMemberId);

        if (members != null)
        {
            member = ConvertDataToMember(members);
        }

        return member;
    }}

ServiceContext объединяет четыре отдельных сервиса, цели которых относительно ясны из CTOR:

public OServiceContext(OpenConfiguration config)
    {
        _username = config.Username;
        _password = config.Password;

        _authenticationService = new AuthenticationService(config.GetEndpointConfigurationFor(nameof(AuthenticationService)));
        _dataService = new DataService(config.GetEndpointConfigurationFor(nameof(DataService)));
        _workflowService = new WorkflowService(config.GetEndpointConfigurationFor(nameof(WorkflowService)));
        _documentService = new DocumentService(config.GetEndpointConfigurationFor(nameof(DocumentService)));

        var viewClasses = AppDomain.CurrentDomain.GetAssemblies()
            .SelectMany(x => x.GetTypes())
            .Where(x => typeof(IOpenHostView).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract && x.IsPublic)
            .Select(x => x)
            .ToList();

        foreach (var c in viewClasses)
        {
            var attribute = c.GetCustomAttributesData()
                .FirstOrDefault(x => x.AttributeType == typeof(OpenViewAttribute));

            if (attribute == null)
                throw new NullReferenceException($"Unable to find '{nameof(OpenViewAttribute)}' on {nameof(IOpenView)} implementation $'{c.Name}'.");

            var viewName = attribute.ConstructorArguments[0].Value.ToString();
            var viewConfig = config.GetViewConfigurationFor(viewName);

            if (viewConfig == null)
                throw new NullReferenceException($"Unable to locate key for Open view '{viewName}'.");

            _viewLookup.Add(c, viewConfig.Key);
        }
    }

Тест как таковой стойки:

    [Fact]
    public void MemberRepository_GetMember_ReturnsValidMember()
    {
        //Arrange

        var mockOServiceConfig = new OpenConfiguration()
        {
            Username = "test",
            Password = "pass",
            Remoting = new OpenRemotingConfiguration(),
            Endpoints = new List<OpenHEndpointConfiguration>(){
                new OpenEndpointConfiguration {
                    Reference = "test", ServiceUrl = "test", DatabaseKey = 1, EnableMessageLogging = true
                } },
            Views = new List<OpenViewConfiguration>(),
            Entities = new List<OpenEntityConfiguration>()
        };
        var mockOServiceContext = new Mock<OServiceContext>(mockOServiceConfig);
        var mockOpenDbContext = new Mock<OpenDbContext>();
        var mockOpenDbSet = new Mock<DbSet<Member>>();

        mockOpenDbSet.Setup(s => s.Find(It.IsAny<int>())).Returns(new Member());
        mockOpenDbContext.Setup(s => s.Set<Member>()).Returns(mockOpenDbSet.Object);

        //Act
        var memberRepository = new MemberRepository(mockOServiceContext.Object, mockOpenDbContext.Object);
        var member = memberRepository.GetMember(1, 1);

        //Assert
        Assert.NotNull(member);
        Assert.IsAssignableFrom<Member>(member);
    } 
}

При этом возникает ошибка -

System.NullReferenceException: 'Ссылка на объект не установлена ​​для экземпляра объекта.' config был нулевым.

В основном параметры недопустимы для конфигурации при отправке в AuthenticationService. Но мой вопрос на самом деле не об исправлении ошибки. Является ли наилучшим подходом спуск по кроличьей норе попыток передать правильные проверенные параметры для всех этих служб? Конечно, есть лучший способ смоделировать это, когда все, что я хочу на самом деле протестировать, это относительно тривиальный метод Get?

Также я знаю, что в зависимости от того, как вы подходите к проверенным службам и данным, модульный тест может видоизменяться в интеграционном тесте. Я просто хотел бы услышать мысли любого, кто имел дело с чем-то подобным. Честно говоря, это первый раз, когда я пытался выполнить модульное тестирование репозитория, и хотя я пытался использовать как можно больше на topi c, я был бы искренне признателен за любые рекомендации.

...