• 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 Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Rob Spoor
  • Tim Cooke
  • Junilu Lacar
Sheriffs:
  • Henry Wong
  • Liutauras Vilda
  • Jeanne Boyarsky
Saloon Keepers:
  • Jesse Silverman
  • Tim Holloway
  • Stephan van Hulst
  • Tim Moores
  • Carey Brown
Bartenders:
  • Al Hobbs
  • Mikalai Zaikin
  • Piet Souris

Injecting specific implementations at unit test time

 
Marshal
Posts: 3653
516
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: 24295
167
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: 3653
516
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: 13262
292
  • 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: 24295
    167
    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.
     
    You showed up just in time for the waffles! And this tiny ad:
    Building a Better World in your Backyard by Paul Wheaton and Shawn Klassen-Koop
    https://coderanch.com/wiki/718759/books/Building-World-Backyard-Paul-Wheaton
    reply
      Bookmark Topic Watch Topic
    • New Topic