Page 2 of 3 FirstFirst 123 LastLast
Results 11 to 20 of 24

Thread: Unit-Testing of Domain Objects and Encapsulation

  1. #11
    Join Date
    Sep 2006
    Location
    UK
    Posts
    8,424

    Default

    Its funny you should talk about reflection, I was having the same discussion with a colleague about this thread. You could use it to do you testing, but it just feels so heavy handed.

    The nice thing is if you are using injection you can plug-in test versions of the objects. It might help to have a concrete example to work with here and we could come up with a way of testing it.

  2. #12
    Join Date
    Nov 2005
    Posts
    112

    Default

    One problem with reflection (apart from being heavy) is that you can't rely on the compiler to let you know when method signatures change.

    And because its test code one would always want to work with the real object without adding proxies and stuff just for testing the object.

    If you are ok with proxies, you could have additional test interfaces for these domain objects which are mixed in using AOP. And the objects themselves would have to implement the getters and setters, though their business interfaces need not necessarily expose them.

  3. #13

    Default Examples

    Quote Originally Posted by karldmoore View Post
    It might help to have a concrete example to work with here and we could come up with a way of testing it.
    Agreed. Let me try to describe some of the problems we are facing.

    Example 1:

    We decided not to provide public constructors, but instead, provide each class with a public static factory method as the only means of getting a new instance. This ensures that all objects are always constructed properly (e.g. we provide initial values for fields that must not be null etc.). Furthermore, we don't provide setters for the private members, because most of them should not be changed directly by other objects. However, in our tests we sometime want to create instances with messed-up state. We do this because we want to test our code against illegal, as well as legal, input.

    Example 2:

    As I may have mentioned, we use Hibernate. When we test our repositories (i.e. DAOs), we want to make sure all mapped properties were populated. However, we do not want to provide getters for all private members of the class, since this compromises encapsulation completely.

    Quote Originally Posted by sabarish View Post
    If you are ok with proxies, you could have additional test interfaces for these domain objects which are mixed in using AOP. And the objects themselves would have to implement the getters and setters, though their business interfaces need not necessarily expose them.
    So we can provide getters, setters and constructors for the classes, but have everybody (except the tests) use them through interfaces, which are narrower. Interesting...

    I'm not sure I understand why I would need AOP for this, though. Could you elaborate on that please?

  4. #14
    Join Date
    Nov 2005
    Posts
    112

    Default

    Quote Originally Posted by nlif View Post
    So we can provide getters, setters and constructors for the classes, but have everybody (except the tests) use them through interfaces, which are narrower. Interesting...
    Exactly. So, though we are compromising on encapsulation, we can use the right layer specific abstractions (kind of different views of the same object) to keep things cleaner.

    We need AOP or something similar because our domain objects are not going to implement these 'test interfaces'.

    This is similar to the discussion that happened earlier on allowing presentation layer to access domain object getters and setters. So the ways to do it would be similar. Sergio's XT modeling framework, part of Spring Modules, may make it easier in case you are using JDK 5.0.

  5. #15
    Join Date
    Dec 2005
    Location
    U-241
    Posts
    237

    Default

    AOP, mixings, introspection, reflection just for simple sanity check.
    It's all hot and interesting but definitely is not my interpretation of kiss
    Spring, it's a wonderful thing...

  6. #16
    Join Date
    Sep 2006
    Location
    UK
    Posts
    8,424

    Default

    Quote Originally Posted by Arno Werr View Post
    AOP, mixings, introspection, reflection just for simple sanity check. It's all hot and interesting but definitely is not my interpretation of kiss
    I would agree, couldn't we go for a simplified version. This usually works for me.

    #1. Want to create objects with messed up states. If collaborating objects actually change the state, ensure that these objects are injected. This means you can inject a test version in that will mess with the states for you.

    #2. Encapsulation you say, are you programming to interfaces? On your business object make all the getters default scope, atleast that way in your unit tests you can access them to make assertions. Ensure all of the code knows nothing about the actual domain object and only ever has references to the interface. If you ensure that the static factory methods return the interface as well, there should be very few direct calls to the REAL domain object.

  7. #17
    Join Date
    Nov 2005
    Posts
    112

    Default

    Quote Originally Posted by Arno Werr View Post
    AOP, mixings, introspection, reflection just for simple sanity check.
    It's all hot and interesting but definitely is not my interpretation of kiss
    True, its a bit too much for testing code. In fact all that AOP, mixins etc are not required unless you want these test interfaces. Assuming the domain entity has a business interface and has all setters and getters in only the implementation class, then the test code can simply cast the domain object to its implementation and directly call the accessors.
    Last edited by sabarish; Dec 15th, 2006 at 05:57 PM.

  8. #18
    Join Date
    Sep 2005
    Location
    Australia
    Posts
    11

    Default

    Quote Originally Posted by nlif View Post
    Agreed. Let me try to describe some of the problems we are facing.

    Example 1:

    We decided not to provide public constructors, but instead, provide each class with a public static factory method as the only means of getting a new instance. This ensures that all objects are always constructed properly (e.g. we provide initial values for fields that must not be null etc.). Furthermore, we don't provide setters for the private members, because most of them should not be changed directly by other objects. However, in our tests we sometime want to create instances with messed-up state. We do this because we want to test our code against illegal, as well as legal, input.
    Sorry, but I'm not sure I understand this.
    If you have some private members that are always correctly initialized by the static factory and can't be changed because you don't provide setters for them, why would you want to set them to illegal values in your tests?
    If no code is able to set your properties to the illegal values why would you write tests for illegal values?

    Quote Originally Posted by nlif View Post
    Example 2:

    As I may have mentioned, we use Hibernate. When we test our repositories (i.e. DAOs), we want to make sure all mapped properties were populated. However, we do not want to provide getters for all private members of the class, since this compromises encapsulation completely.
    In a similar way, if you don't have getters for some members why do you care if they are populated by Hibernate? Who will use those private members if they are not accessible? Do you have to populate them at all?

    Did I misunderstood something?


    Tamas

  9. #19
    Join Date
    Sep 2006
    Location
    UK
    Posts
    8,424

    Default

    Quote Originally Posted by szabtam View Post
    Sorry, but I'm not sure I understand this.
    If you have some private members that are always correctly initialized by the static factory and can't be changed because you don't provide setters for them, why would you want to set them to illegal values in your tests?
    If no code is able to set your properties to the illegal values why would you write tests for illegal values?

    In a similar way, if you don't have getters for some members why do you care if they are populated by Hibernate? Who will use those private members if they are not accessible? Do you have to populate them at all?

    Did I misunderstood something?
    I would agree with the first point. If there is no possible way of illegal data getting in there, what are you actually trying to test for?

    I think the second point is, although getters aren't supplied you still need to ensure you the correct internal state. Collaborators work with this data and the object uses it internally, you need to ensure its correct.

  10. #20

    Default Replies

    Quote Originally Posted by Arno Werr View Post
    AOP, mixings, introspection, reflection just for simple sanity check.
    It's all hot and interesting but definitely is not my interpretation of kiss
    I agree. That's why we decided to post a question in the forum. Whenever my solution starts to get complicated, I always suspect I am looking at things in the wrong way.

    Quote Originally Posted by szabtam View Post
    Sorry, but I'm not sure I understand this.
    If you have some private members that are always correctly initialized by the static factory and can't be changed because you don't provide setters for them, why would you want to set them to illegal values in your tests?
    If no code is able to set your properties to the illegal values why would you write tests for illegal values?
    Good point. I was waiting for someone to bring it up This argument is a good one, and it came up in our internal discussions as well. The counter-argument was, that I may want to test other components, that use my domain object as input, and verify that they can handle incorrect data. But I am not sure that the counter-argument is valid: after all, if there is absolutely no way to construct an object in a certain way, then nobody will ever get it as input...

    Quote Originally Posted by szabtam View Post
    In a similar way, if you don't have getters for some members why do you care if they are populated by Hibernate? Who will use those private members if they are not accessible? Do you have to populate them at all?
    I will explain: let's say that a domain object has a state property. This is saved in the database, and needs to be populated when the object is loaded by Hibernate. However the state is only used by the object itself, so there is no setter and no getter. The object transitions across its state-space in response to events, but no-one can change the state from outside. No one can query on the state , either. Or, at least, not using a getter (i.e. I can ask isFinished(), and get true or false, but not getState(). Therefore, there are no setter or getter, but there is a need to test that the Hibernate mapping is correct. I hope this clarifies it for you.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •