-1

I'm using a DDD approach for the Domain classes. Although, I have a problem on my design, that I'm handling it now but didn't have a good idea to over tackle it.

My Architecture is the follow one:

- Core

  • Application(here I have a bunch of command/queries that use Domain entities and CQRS to process use cases)
  • Domain

-Services

-Infrastructure

-Presentation

My problem relies in the following thing. I have a class called template that implements the interface ITemplate. This interface implements several methods and properties. As we can see above

 public interface ITemplate
 {
        public int Id { get; set; }

        string Name { get; set; }

        string Definition { get; set; }

        ISource Source { get; set; }

        ITemplateDefinition GetTemplateDefinitionObject();

        void SetTemplateDefinition(string templateDefinitionString);
 }

Inside a command, placed on the Application folder, I have the following:

public async Task<Unit> Handle(UpdateTemplateCommand request, CancellationToken cancellationToken)
{
       var templateDto = request.Template;


       var sourceForTemplate = await SourceRepository.SingleAsync(x => x.Id == templateDto.SourceId);

       if (sourceForTemplate == null)
       {
           throw new NotFoundException(nameof(Domain.Entities.Source), request.Template.SourceId);
       }

       var templateToUpdate = await TemplateRepository.SingleAsync(x => x.Id == templateDto.Id);

       if (templateToUpdate == null)
       {
            throw new NotFoundException(nameof(Domain.Entities.Template), request.Template.Id);
       }


       if (!string.IsNullOrEmpty(templateDto.Definition))
       {
            try
            {      
              **templateToUpdate.SetTemplateDefinition(templateDto.Definition);**
            }
            catch (Exception e)
            {
               throw e;
            }

        }
   }
          TemplateRepository.UpdateRFEntity((Domain.Entities.Template)templateToUpdate);

The line with the ** surrounding is my problem.

When Unit testing this I can't fake it since the repository returns a concrete implementation and not a interface, which i think is the right way, since when dealing with a ORM like EF, with the possibility to track entities and other mechanisms we shouldn't loose that by mapping responses to a interface.

Does anyone have a idea how to do it cleaner in order to be able to mock class calls without the need to make members virtual, since i have already a interface, and not having to transpose all responses to interface?

  • Can't you mock your TemplateRepository using a factory? – πάντα ῥεῖ Mar 24 at 17:15
  • Also fix you code formatting pease. It doesn't look right. – πάντα ῥεῖ Mar 24 at 17:20
  • Hi, i tried to fix it but it's not easy to make it like it appears on IDE. Is it better? When you say a factory to mock what value would bring to the table? Thanks – joseFrancisco Mar 24 at 18:47
  • 1
    "The line with the ** surrounding is my problem." I don't see any asterisks. Also, why have the interface if you don't use it as the return type for your template repository? – Flater Mar 24 at 22:25
  • 1
    @joseFrancisco avoiding virtual without a real need to is a design fail. Find a real reason to avoid it or get over it. – candied_orange Mar 25 at 15:26
0

When Unit testing this I can't fake it since the repository returns a concrete implementation and not a interface, which i think is the right way

Unit tests test ONE thing, hence why they are called "unit" tests. If you are unit testing your command handler, all of its dependencies (including the repository) should be mocked, at which point your problem becomes a non-issue.

which i think is the right way, since when dealing with a ORM like EF, with the possibility to track entities and other mechanisms we shouldn't loose that by mapping responses to a interface.

I understand where this comes from. If that entity leaves the repository and then makes it back into the repository, it's nice to have the change tracker already know about it.

However, that is irrelevant for unit tests of a command handler, which shouldn't be using a real repository nor the EF db context inside of it.

Does anyone have a idea how to do it cleaner in order to be able to mock class calls without the need to make members virtual

Don't create mocks by deriving objects. Give your object (in this case the repository) an interface, let consumers work with the interface instead of the concrete type, and then created a mock from that interface. This means that your consumers are unaware of (and indifferent to) whether the depedency they've been handed is a "real" object or a mocked one.

since i have already a interface, and not having to transpose all responses to interface?

You're already mostly there. You didn't post the relevant code, so make sure that your command handler's dependencies (i.e. the SourceRepository and TemplateRepository) are using the interface type, not the concrete type. At that point, just create a mocked repository (i.e. a class that implements the necessary repository interface) and inject that as the dependency of your command handler.

How you create your mock is up to you. You could use Moq, NSubstitute, or you could implement your own.

|improve this answer|||||
  • Flater please see my next above comment, since I can reply with clarity on the comment section. – joseFrancisco Mar 26 at 1:43
  • @joseFrancisco: Please don't post answers as a way to ask questions. If it's a relevant clarification to the question, edit the question. If it's a new question, post a new question. – Flater Mar 26 at 9:54
  • @joseFrancisco: There is a lot of information missing to know whether your suggested change works for the classes and interfaces you're working with. This is currently not meaningfully answerable. My advice is to follow a guide/tutorial on unit testing in order to see the ins and outs and then be able to apply them to your scenario. – Flater Mar 26 at 9:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.