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?

8
  • Can't you mock your TemplateRepository using a factory? Commented Mar 24, 2020 at 17:15
  • Also fix you code formatting pease. It doesn't look right. Commented Mar 24, 2020 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 Commented Mar 24, 2020 at 18:47
  • 2
    "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
    Commented Mar 24, 2020 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. Commented Mar 25, 2020 at 15:26

2 Answers 2

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.

3
  • Flater please see my next above comment, since I can reply with clarity on the comment section. Commented Mar 26, 2020 at 1:43
  • 1
    @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
    Commented Mar 26, 2020 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
    Commented Mar 26, 2020 at 9:56
0

a ORM like EF, with the possibility to track entities and other mechanisms we shouldn't loose that by mapping responses to a interface.

You don't lose that change tracking by mapping to an interface.

Downcasting a variable's type does not change the object itself.

public class Foo : BaseFoo, IFoo {}

var foo = new Foo();

IFoo ifoo = foo;
Foo foo2 = (Foo) ifoo;

BaseFoo basefoo = foo;
Foo foo3 = (Foo) basefoo;

At no point did the object we instantiated change. Only one object was created, and we now have five references to the same object - some of them (ifoo, basefoo) are not aware of the concrete type, others are (foo, foo2, foo3), but that doesn't matter. The object itself that is being referenced is still of that concrete type.

Take the following operation:

xxx.Bar = "new bar value";

Regardless of whether xxx is replaced by foo, foo2, foo2, ifoo 1 or basefoo 2, in all cases the db context will track that changed value, and it will commit that changed value when you then call SaveChanges().

The type of the variable itself doesn't matter. As long as it refers to the object that EF created for you, it will be tracked by EF.


1 This does assume that the IFoo interface contains the setter for Bar.
2 This does assume that the BaseFoo base class contains the setter for Bar.


This, in turn, should cause you to reevaluate the decision to not use an interface as a return type, which then solves your issue at hand.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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