2

both unit tests and interfaces to the domain objects are very common here on SO, just that the answers that I find I can not do the two concepts fit together.

According to this topic Should Domain Entities be exposed as Interfaces or as Plain Objects?

I would not have reason to create interfaces for my items but at this point I am in difficulty in creating the test

I do a quick example:

public MyClass1
{
  public int id {get;set;}
  public MyClass2 Class2{get;set;}
}

how can I test MyClass1 isolating it from MyClass2 if not creating his own interface then using moq to create an implementation in the test dummy?

MyClass1 mc1 = new MyClass1();
IMyClass2 moqC2 = Moq.Get<IMyCLass2>();
mc1.Id = 1
mc1.Class2 = moqC2 

Aseert.That(mc1.Id, Is.EqualTo(1));
Aseert.That(mc1.Class2 , Is.EqualTo(moqC2 ));

without interface tests on MyClass1 can fail if MyClass2 has some problem

EDIT

in real project MyClass1 and MyClass2 have over 20 property (with explicit get and set) and some method to do complex operation. Here i post a basic example only for speaking about their reference

EDIT 2 to reply to jgauffin and Eben Roux good comments

some more details about my case:

According to user spec one of my primary object is "Activity" for each activity there are many status, results, peoples and each activity as society, type and classification property.

But every one of this object can live even without activity, for example user want to create a table of status with all possible status and this must be done before a single activity can be created, idem for society and all other reference.

Some are only Lookup table and have ad id, a description a start and end date and an order property.

Other (society, people and result) are complex object with other property and references (society have a type, contracts, list of employee, list af structures and processes; person has office property, list of knowledges, history of promotion and so on; the domain is much more complex with over 140 entities, simply I can not bring it back here all, hope this example is enough)

So all this object must be created without any reference to an activity but an activity can have a reference to all

A tiny part of my model

Model

Community
  • 1
  • 1
gt.guybrush
  • 1,320
  • 3
  • 19
  • 48
  • this is still too abstract for me to grasp. Can you add a specific example to illustrate the relation between the objects? – jgauffin Jun 03 '14 at 08:34
  • For Edit 2: you should not have references to the other ARs. You can use Id/VO. When you need the instance you can go and fetch it based on the Id. – Eben Roux Jun 03 '14 at 09:11
  • hope image can help more. as said above each object can exist alone (maybe with exclusion of promotion that is a ManyToMany relathionship) – gt.guybrush Jun 03 '14 at 09:21
  • just to emphasize the concept, all entities represented must allow CRUD operations as users have asked to have full freedom in the management of all service tables in addition to the main tables – gt.guybrush Jun 03 '14 at 09:33
  • 1
    If CRUD is an requirement you should not use DDD. One of the important things in DDD is to protect the domain model, which do not work very well with CRUD. – jgauffin Jun 04 '14 at 12:15
  • but CRUD operaion will be done in repository (data access layer with nhibernate), my object have no knowledge about them – gt.guybrush Jun 04 '14 at 12:23

5 Answers5

3

Even if it's sample code, that is not a domain entity. It's an anemic domain model and I don't see why you should test it at all, as any code in your application code put that model in an inconsistent state.

When you test domain entities you should test the behavior. And behavior are added using methods in your entities. The easiest way to get started is to make all property setters private.

public User
{
  Address _address;

  public User(int id, Address address)
  {
     //assign
  }

  public int Id {get;private set;}

  public bool IsAddressSame(Address address)
  {
      if (address == null)
          throw new ArgumentNullException("address");

      return address.Equals(_address);
  }

  public void Move(Address newAddress)
  {
      if (address == null)
          throw new ArgumentNullException("address");

      var old = _address;
      _address = newAddress;
      DomainEvent.Publish(UserMoved(_old, newAddress);
  }  
}

Now you can test the behavior of the address methods.

how can I test MyClass1 isolating it from MyClass2 if not creating his own interface then using moq to create an implementation in the test dummy?

Do not create interfaces for your domain entities. the purpose of interfaces is to create abstractions to remove dependencies from other parts of the application. What would be the point of abstracting away the domain model? In DDD it's the heart of your application. You do not have one without it.

As the state is now protected, you know that each entity have a correct state. You do therefore not need to isolate User from Address. Instead just write tests for the methods that you have created.

Update to answer comment

"When you test domain entities you should test the behavior" seem good but in TDD i have to write test before and after create implementation, so if i want a Class1 with a Class2 property i first have to test that i have this property

No. In TDD you should also test behavior. The dependencies are driven by the behavior and not vice versa.

What I mean is that there is no way at all to actually KNOW that there is a relationship between the User and the Address unless you have a spoken requirement that something should be done with an user address.

And with that requirement you should test the method on the User class and not violate Law of Demeter by accessing the address directly.

jgauffin
  • 99,844
  • 45
  • 235
  • 372
  • "When you test domain entities you should test the behavior" seem good but in TDD i have to write test before and after create implementation, so if i want a Class1 with a Class2 property i first have to test that i have this property – gt.guybrush Jun 02 '14 at 14:55
  • No. In TDD you should also test behavior. The dependencies are driven by the behavior and not vice versa. – jgauffin Jun 02 '14 at 16:49
1

Generally in such situation you can't get rid of the depenency of MyClass1 on MyClass2 and you have to test them both at the same time. This is one of the reasons why a class should not be dependant on other classes but on interfaces instead. Code that you presented is poorly designed as it violates one of the SOLID rules - the dependency injection. However even in such case there is hope for your code to prepare your unit test only against MyClass1 but you must fullfil one condition - all methods and properties of MyClass2 that you want to Setup with mock must be declared as virtual. Thanks to this Mock will be able to override them with its own implementation. Otherwise it you try to use Setup or Verify on non-virtual method or property you will end up with an exception. To get mock of class you simply do the same as to obtain mock of interface:

Mock<MyClass2> mock = new Mock<MyClass2>();
mock.Setup(c => c.Method());
mr100
  • 4,340
  • 2
  • 26
  • 38
  • since i use NHibernte, all object properties and method are virtual, so this can be solution – gt.guybrush Jun 02 '14 at 14:47
  • But still the better option is to have dependency injection in your application. Take into account what happens if you decide to change NHibernate for different ORM. If you have everything separated with interfaces then this change is fairly simple. – mr100 Jun 03 '14 at 09:58
  • i have all build up with ninject in my bootstrapper, out of Data access layer i have no reference to nhibernate but only to repository and UoW interface. But how can DI enter in domain layer class? – gt.guybrush Jun 03 '14 at 11:56
1

In general, I'd say don't create interfaces just because you need them in your tests. Create interfaces to make an abstraction (a real abstraction, not an invented one).

As for your question on how to test your code, it depends, if this is actually the code, I would argue that that's probably not a test you need:

Aseert.That(mc1.Class2 , Is.EqualTo(moqC2 ));

What are you testing here? That auto-implemented properties work as they should? You could probably get rid of this test, because it has very little value. (Unless this was just an example, if it was, can you post a different, more real, example?)

Kenneth
  • 28,294
  • 6
  • 61
  • 84
  • don't create interfaces just because you need them in your tests.Ok taht's corect and i agree, good point.in that case i will use mr100 of virtual property. In TDD iam testng that my object has a Class2 Property – gt.guybrush Jun 02 '14 at 14:23
0

Your entities and value objects do not need interfaces.

If your example is a real scenario then you would need to reconsider your design. An aggregate should not hold a reference to another aggregate. As such the aggregate can, and should, be tested in its entirety.

Edit:

An aggregate contains other objects that cannot exist without the root. The most common example being Order/OrderLine. An OrderLine has no meaning without an Order. In no way would one be interested in an OrderLine that is standing alone.

I know that one could argue that your Activity cannot exist without being related/belonging to a Society. But that is where the difference lies. An Order would have little meaning without a Customer. Ownership, therefore, does not determine aggregation.

Using the Order example one could represent that Customer in various ways. If there is no Customer aggregate/entity then it could even be a value object in the order. This is how one may deal with cash sales, for instance. However, having a reference to a full Customer aggregate is problematic since retrieving an Order from the data store now adds the complexity of how to get the Customer object in there and it probably wouldn't stop there either. What about the customer's addresses. What about the OrderLine's Product and that product's PreferredSupplier, etc.

DDD is all about hard edges to boundaries in order to have low coupling. In the Order/OrderLine case the Customer could be represented either by the customer's Id or some value object that may even contain some de-normalized data like the customer name.

In your case, instead of Customer -> Order, you have Society -> Activity.

Hope that helps :)

Eben Roux
  • 12,983
  • 2
  • 27
  • 48
  • A simple example: user can add, edit and delete Society and Activity; every activity must have a society associated. how can i do it without a reference? P.S. no controversy, I'm really interested in an alternative route to my usual idea of ​​having objects linked together – gt.guybrush Jun 02 '14 at 14:58
0

I would not have reason to create interfaces for my items but at this point I am in difficulty in creating the test

Lots of people that start testing tend to use mocks in order to create stub/fake/dummy instances. It has its own pros (it is possible to create an instance within one line of code) and cons (they have no behaviour that should be specified, sometimes it is difficult to set up right behaviour).

I faced the same issues with arranging testing data but I found several solutions.

First solution is ObjectMother pattern.

var myClass1 = ClassBuilder.GetClass1();
var myClass2 = ClassBuilder.GetClass2();

Methods GetClass1() and GetClass2() encapsulate creation logic.

Second one is Test Data Builder pattern.

var myClass1 = new Class1Builder.Build();
var myClass2 = new Class2Builder.WithSomeProprty().Build();

Class1Builder and Class2Builder implement fluent interface that allows us to chain methods with clear enough names.

There are two old good posts about Object Mother and Test Data Builder patterns.

I have not used but some people use the following frameworks to build test data:

Ilya Palkin
  • 14,687
  • 2
  • 23
  • 36
  • i currentrly use moq and AF in test, i even try fluent factory (similiar to you with begin and end but i need even some reuired fields so i need an order fluent, can find example here http://stackoverflow.com/questions/18721419/create-a-base-fluent-ordered-constructor) for create my domain object but stop becaus it add to much complexity: constructor and property works well in my team. But don't see how creating object in an external class (factory, mother or builder) can remove dependency between object. In your example claim test will fail if Recipient has some error: i want avoid this – gt.guybrush Jun 03 '14 at 19:37
  • That external classes do not remove dependency. They simplify creation of your domain objects that are used in your tests. Instead of setting up mocks it is OK to build up real instances. Sometimes it is even easier since builders/factories can be reused widely. Mocking is essential when you break dependency on File System, Data Base or Web Services. If you set up real instances your tests will be fast and isolated enough. Infrastructure of your project should not influence on design of Domain Entities/ Domain Model. – Ilya Palkin Jun 03 '14 at 20:33
  • like i said i tried to use the factory, but if you're dealing with mandatory fields, realize cost too much in relation to the benefits they give. If you are interested i just create new question here http://stackoverflow.com/questions/24032235/c-sharp-constructor-vs-builder-pattern The only requirement to use the builders I see is if I have to use dependency injection and my builder wants you have values ​​(strings or numbers) set at runtime. In my vision mocking is essential even for writing unit test of every class otherwise they are integration tests, not unit. – gt.guybrush Jun 04 '14 at 08:14