Injecting Mock Beans Into Spring Context

Discussions

News: Injecting Mock Beans Into Spring Context

  1. Injecting Mock Beans Into Spring Context (16 messages)

    Today I was googling about mocking when I have found next question:

    "Injecting mock beans into spring context for testing. What I want to be able to do is via the HotswappableTargetSource override the bean definitions of select beans in my application context with my test versions and then run the test.
    Then for each test case I'd like to specify which beans I want to be hot swappable and then each test must be able to create its own mock versions and swap those in, and be able to swap back again."

    And there you can find a solution using ProxyFactoryBean and HotSwappableTargetSource. Well it is a solution for me a bit complicated, if I should do the same I would do usingStaticApplicationContext class, because from my point of view, environment is more controlled and easy to understand. Of course the easiest solution is using Spring 3.1 Profile feature, but meanwhile it is a milestone/RC or simply because you will not be able to change Spring version, I will show you how to use StaticApplicationContext and how to inject mocked beans.

    StaticApplicationContext is an implementation of ApplicationContext interface which supports programmatic registration of beans and messages, rather than reading bean definitions from external configuration sources. StaticApplicationContext has been created mainly for testing purpose. To solve the problem  we focus, some of registered beans will be the "real" beans, but others will bemocked beans with all their interactions.

     

    Full Post

    Threaded Messages (16)

  2. Mock beans in spring context[ Go to top ]

    The problem with using StaticApplicationContext is that you have to explicitly create BeanDefinition objects.  You can't register existing object with it.

     

    Why not just use your mock toolkit (example using jmock)?

     

    final ApplicationContext applicationContextMock = mockery.mock(ApplicationContext.class);

    final SomeBean someBean = mockery.mock(SomeBean.class);

    mockery.checking(new Expectations() {{

      allowing(applicationContextMock).getBean(with("someBean"));

      will(returnValue(someBean));

    }});

     

    If you then want to mix mocks and regular beans, you could still make the mock application context the parent of the StaticApplicationContext.

     

  3. Any reason you want to do this type of a test instead of just unit testing your classes separately and injecting mocks into them? 

  4. "To solve the problem ..."[ Go to top ]

    DI injects dependencies but doesn't prevent dependencies. Quite the contrary: DI fosters strongly coupled designs which basically are untestable by UnitTests. Dependencies are bad, injected dependencies are by no means better. Instead of 'mock juggling' get down to the root of the problem and ditch DI. Design decoupled and testable applications instead of mindlessly following the DI-AntiPattern.

  5. "To solve the problem ..."[ Go to top ]

    DI injects dependencies but doesn't prevent dependencies. Quite the contrary: DI fosters strongly coupled designs which basically are untestable by UnitTests. Dependencies are bad, injected dependencies are by no means better. Instead of 'mock juggling' get down to the root of the problem and ditch DI. Design decoupled and testable applications instead of mindlessly following the DI-AntiPattern.

     

    Well... My DI applications are perfectly unit-testable. Am doing something wrong?

    Seriously, without dependencies how would you implement cross-component interactions? application-wide?

  6. "To solve the problem ..."[ Go to top ]

    As I said in post I prefer not to inject mocks into Spring Context, I prefer designing classes for better test. But I could understand that something could find this useful, and for this reason I decided to investigate and post about it.

     

    It is true that with StaticApplicationContext you should define explicetly dependencies, but if instead of using one big application context file you use multiple application contexts files would be more easy.

     

    Thank you very much all of you for reading my post.

    Alex.

  7. "To solve the problem ..."[ Go to top ]

    "My DI applications are perfectly unit-testable."

    That's why we see posts like the original post and so many untestable Spring applications in the real world.

    "without dependencies how would you implement cross-component interactions"

    It's your task to manage exchange of data between loosely coupled components. DI fosters strong coupling and leads to 'spaghetti design'.

  8. "To solve the problem ..."[ Go to top ]

    "without dependencies how would you implement cross-component interactions"

    It's your task to manage exchange of data between loosely coupled components. DI fosters strong coupling and leads to 'spaghetti design'.

     

    I agree that it is developer's task to integrate components; but back to the question - practically, what does it mean implementation-wise?

  9. "To solve the problem ..."[ Go to top ]

    Design decoupled and testable applications instead of mindlessly following the DI-AntiPattern.

    That's oversimplifying it greatly. I can write strongly coupled and completely untestable code without using a trace of DI, the same way I can write code with loose coupling and strong cohesion that is perfectly unit-testable while using DI all the way. It's in the developer, not the tool.

    And I reject the premise that DI is, by definition, strongly coupled. One service referencing another service by interface, is that strongly coupled? If so, the only way to achieve loose coupling (by your definition) is to have your entire application implemented in a single method. And when an "anti pattern" becomes the prevailing design, maybe it's time to reevaluate if it's still "anti"...

  10. "To solve the problem ..."[ Go to top ]

    I agree with you. In fact is the developer who writes testable code or not, not using one technology or another. It is true that some technologies can help you, but anyway all is in your hands.

  11. DI-AntiPattern[ Go to top ]

    You can only 'inject' dependencies because the dependencies are already in your design. You wouldn't need dependency injection if you had no dependencies.

    "One service referencing another service by interface, is that strongly coupled?"

    Yes, undoubtedly.

    If so, the only way to achieve loose coupling (by your definition) is to have your entire application implemented in a single method.

    Quite the contrary. Loose Coupling means that a component doesn't know and depend on other components and therefore also needs no 'injected' dependencies.

     

  12. DI-AntiPattern[ Go to top ]

    "Quite the contrary. Loose Coupling means that a component doesn't know and depend on other components and therefore also needs no 'injected' dependencies."

    Could you elaborate more on this. Maybe an example would do it?

  13. DI-AntiPattern[ Go to top ]

    >>"One service referencing another service by interface, is that strongly coupled?"

    > Yes, undoubtedly.

    In your world it may be. But once upon a time programming against interfaces rather than implementations were considered loose coupling. Comparatively.

    > Loose Coupling means that a component doesn't know and depend on other components and therefore also needs no 'injected' dependencies

    Loose coupling can mean a lot of things depending on context and it is always relative to something.

    No need to pretend there is a universal definition.

    With regards to the "DI antipattern", I find it hard to imagine a component A that needs user data from another component with interface BI.getUser(int id) not knowing about interface BI.

    Care to explain how this would work out in your world?

  14. DI is an AntiPattern[ Go to top ]

    Loose coupling can mean a lot of things depending on context and it is always relative to something.

    Coupling is a relatively well understood concept: http://en.wikipedia.org/wiki/Coupling_%28computer_science%29

    With regards to the "DI antipattern", I find it hard to imagine a component A that needs user data from another component with interface BI.getUser(int id) not knowing about interface BI.

    BI.getUser(int id) creates a dependency on BI, User and - transitively - anything that can be accessed form User. If User is an Entity from which you can access other Entities (a la JPA) this method probably creates a dependency on all Entities in the database. Yep, this is an AntiPattern.

    The alternative is not to generously create dependencies but to pass the necessary data as arguments to the method. The 'User' entity is most probably not required for your service. You need a telephone number, a date of birth, an address, ... but neither a dependency to a 'BI'-DAO nor to User (an all other) entities.

     

  15. DI is an AntiPattern[ Go to top ]


    Coupling is a relatively well understood concept:http://en.wikipedia.org/wiki/Coupling_%28computer_science%29

    Good! So, apparantley is loose coupling:

    http://en.wikipedia.org/wiki/Loose_coupling

    And I qoute: "Strong coupling occurs when a dependent class contains a pointer directly to a concrete class which provides the required behavior. The dependency cannot be substituted, or its "signature" changed, without requiring a change to the dependent class. Loose coupling occurs when the dependent class contains a pointer only to an interface, which can then be implemented by one or many concrete classes."

    Clearly, it disagrees with you.

    >BI.getUser(int id) creates a dependency on BI, User and - transitively - anything that can be >accessed form User. If User is an Entity from which you can access other Entities (a la JPA) this > method probably creates a dependency on all Entities in the database.

    I completly agree. And in some circumstances that may be fine, in others it is not. If A and BI share the domain model and running in the same JVM this may work just fine. If they are remote to each other, it will probably not. 

    > Yep, this is an AntiPattern.

    No, this is not per definition an antipattern. Weather this is a problem or not depends on the situation where A and BI are used.In a web-client accessing a local database it may work fine. In a remote service call it may not.

    > The alternative is not to generously create dependencies but to pass the necessary data as arguments to the method. The 'User' entity is most probably not required for your service. You need a telephone number, a date of birth, an address, ... but > neither a dependency to a 'BI'-DAO nor to User (an all other) entities.

    Your suggestions for improvement are all well and will lead to a looser coupling.

    But my original question on how A can get the data without knowing the interface BI still remains unanswered. And that is were DI occurs here.

  16. I wonder how many answers I can see if the question is about CDI, JSF, Seam ...

  17. Loose Coupling[ Go to top ]

    Loose coupling manifests itself differetly in different types of systems.  Interfaces with injected implementaitons do provide a level of loose coupling, but as the application model gets more distrubuted (we connect to more services, build-less-borrow-more) loose coupling means decoupling sub systems of your application completely through a service or messaging interface.  I blogged recently on the topic: http://blogs.mulesoft.org/every-time-you-ignore-loose-coupling-a-little-donkey-dies/