• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Paul Clapham
  • Ron McLeod
  • Bear Bibeault
  • Liutauras Vilda
Sheriffs:
  • Jeanne Boyarsky
  • Tim Cooke
  • Junilu Lacar
Saloon Keepers:
  • Tim Moores
  • Tim Holloway
  • Stephan van Hulst
  • Jj Roberts
  • Carey Brown
Bartenders:
  • salvin francis
  • Frits Walraven
  • Piet Souris

Injecting specific implementations at unit test time

 
Marshal
Posts: 3355
492
Android Eclipse IDE TypeScript Redhat MicroProfile Quarkus Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
During unit testing, depending on the test case, I need to use different implementations of a storage class, including contrived instances which have a particular behaviour needed to satisfy the test case.

What I am doing below does work, but I feel that there may be a better what to do this, maybe by using some features of CDI or using something like Mockito.

Any suggestions?


 
Saloon Keeper
Posts: 23040
157
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm not sure how unit test works with CDI, since I started out using Spring and Spring and CDI were not playing well together last time I tried - which admittedly was a long time ago.

For Spring, I could just run a suite using multiple wirings. Spring doesn't depend on a container, however, and as far as I know, CDI does, so that part isn't clear to me.

I should point out that strictly speaking "Unit" tests are not supposed to call other modules anyway. That's an integration test. However, JUnit works pretty well at the integration test level also.

Also, strictly speaking, if you have plug-replaceable components and the components are all unit-test valid, then a test using one should potentially be a test for all.

I'd also argue that when you are testing anything that needs to call out for services, whether it's mail, web services, or something more exotic, then it's best that you call a mock service and not a live service. Obviously especially for email tests, where you don't want to spam the world, but also generally, since you're less likely to receive unexpected responses from a standard mock than a live component.
 
Ron McLeod
Marshal
Posts: 3355
492
Android Eclipse IDE TypeScript Redhat MicroProfile Quarkus Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:I'm not sure how unit test works with CDI, since I started out using Spring and Spring and CDI were not playing well together last time I tried - which admittedly was a long time ago.

For Spring, I could just run a suite using multiple wirings. Spring doesn't depend on a container, however, and as far as I know, CDI does, so that part isn't clear to me.


I've never needed to use Spring so I'm not sure if some of the methodologies uses with Spring would also be applicable for Jakarta and CDI.

I should point out that strictly speaking "Unit" tests are not supposed to call other modules anyway. That's an integration test. However, JUnit works pretty well at the integration test level also.

Also, strictly speaking, if you have plug-replaceable components and the components are all unit-test valid, then a test using one should potentially be a test for all.


This is a unit test, but the unit under test has injected dependencies which effect its behaviour.  I have separate unit tests for those dependencies to verify their behaviour.

I'd also argue that when you are testing anything that needs to call out for services, whether it's mail, web services, or something more exotic, then it's best that you call a mock service and not a live service. Obviously especially for email tests, where you don't want to spam the world, but also generally, since you're less likely to receive unexpected responses from a standard mock than a live component.


No live services in my unit test.  For testing, I have a store implementation which simply uses a Map.  
In production it would use a database, document store, or a storage service.
 
Saloon Keeper
Posts: 12622
273
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This seems like a pretty simple test case to me. It boils down to two things:

  • You want to test that your manager service throws an exception.
  • You want to test that a mock service it depends on has been called a certain number of times.

  • You don't need CDI. Just the standard tools that JUnit and your mocking framework offer you:


    1. Mock dependencies.
    2. Configure test object.
    3. Configure expected exceptions.
    4. Call test object.
    5. Verify return value.
    6. Verify calls on mocked dependencies.
     
    Tim Holloway
    Saloon Keeper
    Posts: 23040
    157
    Android Eclipse IDE Tomcat Server Redhat Java Linux
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Spring is a generic bean factory and  IoC injection framework and can be used anywhere, including in stand-alone apps. It predates CDI and provides an extensive set of services, including Spring Data, which takes care of a lot of the grunt work for transaction-based persistent storage operations. So when CDI first came out, naturally I wanted to get the best of both worlds, just as I could using the JSF/Spring bridge where JSF ManagedBeans could freely interconnect with Spring beans and Spring beans and their properties could be referenced on View Templates using Expression Language (EL). But that's just background, not of particular interest here.

    @Inject'ed items are not magic. All the @Inject annotation does is mark the property as something for the framework to wire into. If a unit test wants to manually set the @Inject'ed property in lieu of a CDI container doing so, there is absolutely nothing wrong with that. And, after all, one of the primary benefits of systems like jUnit is that they can do testing without the tremendous overhead it takes to crank up a container.

    Beyond those comments, I'll defer to Stephan who's more in touch with your particular situation.
     
    reply
      Bookmark Topic Watch Topic
    • New Topic