Testing Blog

TotT: Using Dependancy Injection to Avoid Singletons

quinta-feira, maio 15, 2008
Share on Twitter Share on Facebook
Google
Etiquetas: TotT

12 comentários :

  1. Calvin Spealman18 de maio de 2008 às 15:34:00 GMT-7

    This doesn't cover a few downfalls to the approach.

    It requires the users of the client know about where to get the singleton and it forces them to access it for every creation of the client class.

    Another problem is that the singleton that this ignores the difference in when the singleton is acquired, which could have important implications that need to be addressed.

    It should be included in such a suggestion that the client class take the singleton injection as an optional parameter, and access the singleton by default, possibly and specifically on each use of the singleton.

    ResponderEliminar
    Respostas
      Responder
  2. Ran Biron19 de maio de 2008 às 11:07:00 GMT-7

    After several failures, we (I and my team in the undisclosed company I work for) got to couple of conclusions:
    1. DI frameworks (e.g. Spring) are extremely friendly for testing.
    2. If you can't use a DI framework, create (a simple) one.
    Now (2) requires some explanation – what we do is have one real singleton – The singleton (application context, container, god – take your pick) which acts as a very restricted access map to several contexts "hubs". Each hubs converse directly with the map, first loading it with the required objects, then extracting and typecasting as needed. Context objects have a very small footprint on construction and are only initialized on event (application init) / request (same as real singletons)
    Testing is facilitated in either of two ways:
    1. If you only need a small number of mock contexts, you create them and load them manually into the singleton map. Future requests will retrieve them. On tests teardown, you empty the entire map.
    2. If you need a large number of mock contexts (big unit tests / integration tests), you just fire one (or more) of the real hubs and overwrite only what's needed in the map (if anything is) with mock implementations.

    This approach has the merit of being very easy on production code and yet (almost) as testable as real DI.

    ResponderEliminar
    Respostas
      Responder
  3. Unknown19 de maio de 2008 às 23:03:00 GMT-7

    To be honest, I do not see the advantage...

    With the first implementation of the Client-Class, it would have been possible to do:

    Client c = new Client();
    client.process();

    That's all... what's the drawback here?

    ResponderEliminar
    Respostas
    1. Leo Gutierrez R25 de dezembro de 2016 às 16:02:00 GMT-8

      Hmmm, the advantage is that with the second approach, we have extracted the Server creation which will allow us to mock it. That wasn't possible with the first approach.

      Eliminar
      Respostas
        Responder
    2. Responder
  4. Unknown20 de maio de 2008 às 09:43:00 GMT-7

    It's hard to test code that uses singletons. << understatement of the year :P
    We have had alot of luck using DI for testing, and when singletons are necessary provide an alternative getInstance method which takes in the parameters to construct the object with for testing.

    ResponderEliminar
    Respostas
      Responder
  5. David20 de maio de 2008 às 15:31:00 GMT-7

    For this thing I use Guice.

    ResponderEliminar
    Respostas
      Responder
  6. Gauthier20 de junho de 2012 às 07:40:00 GMT-7

    years after... :) well, but PHPUnit official documentation is still linking to this blog post so...

    This post is a great and clear explanation of DI benefit at time of unit testing code, but in any case does it demonstrate what problems singletons are causing when unit testing code.

    As said haemi, the first Client.process() method implementation could (not should :)) have been done like this:

    public int process(Params params) {
    Server server = new Server();
    Data data = server.retrieveData(params);
    ...
    }

    In this case, we don't have any singleton involved, but we still cannot unit test this method because of a hard dependency on Server class.

    Indeed, the biggest issue with singleton is to unit test it's different methods independently, since you're not supposed to be able to reset the instance between method calls.

    Using introspection (or, but it's kind of ugly, implementing a resetInstance() public method to delete the current instance and allow instantiating a new one), you can manage to unit test a singleton's methods.

    Tu sum up, dependency injection and singletons are not related in any way!

    ResponderEliminar
    Respostas
      Responder
  7. roni3 de outubro de 2014 às 02:26:00 GMT-7

    It's NOT hard to test code that uses singletons
    It's easy.

    This is how I test a client that uses a Singleton:
    First, I refactor the code that obtains the Singleton instance into a new protected method, as follows:

        public class Client {
           public int process(Params params) {
              Server server = obtainServer();
              Data data = server.retrieveData(params);
              ...
           }

           //new method
           protected Server obtainServer() {
              return Server.getInstance();
           }

        }

    Then I test it using a mock Server as follows:

        public class ClientTest extends Client {
           public void testProcess() {
              Client c = new Client() {
                 @Override protected Server obtainServer() {
                    return new MyMockServer();
                 }

              };
              assertEquals(5, c.process(params));
           }

    ResponderEliminar
    Respostas
    1. Unknown25 de setembro de 2016 às 07:56:00 GMT-7

      Sorry to ask this after so long, but can you explain/point a source about how to create your own mock client?

      Thanks!

      Eliminar
      Respostas
        Responder
    2. Anónimo15 de janeiro de 2018 às 10:55:00 GMT-8

      We used this sort of idea extensively on the Iridium Satellite payload project in the late 1990's. Every single interface had an include file with dependency inline functions, that so by swapping the includes you could mock *everything*. As a result, nobody could read anybody else's code because the language of each service was entirely different, and more or less, random.

      Eliminar
      Respostas
        Responder
    3. Responder
  8. JB19 de novembro de 2014 às 02:29:00 GMT-8

    Sure, but still ur API kind of s*cks. It is not clear hat Client has a strong dependency on Server - whether it is inside the public process() or protected obtainServer() method - unless it is properly documented. Dependency Injection shows off these dependencies right in the API. And you would have to create another subclass on every reuse of Client that needs a different logic to obtainServer(). Not to mention that - at least for me - it seems way out of scope for a client to obtain the server. Just my 2 cents.

    ResponderEliminar
    Respostas
      Responder
  9. Alexander Todorov4 de novembro de 2015 às 15:03:00 GMT-8

    Btw guys, you have a typo in the title of this page. See Dependancy vs Dependency.

    I was spell checking an article which includes a link to this page and this showed up.

    ResponderEliminar
    Respostas
      Responder
Adicionar comentário
Carregar mais...

The comments you read and contribute here belong only to the person who posted them. We reserve the right to remove off-topic comments.

  

Labels


  • TotT 114
  • GTAC 61
  • James Whittaker 42
  • Misko Hevery 32
  • Code Health 31
  • Anthony Vallone 27
  • Patrick Copeland 23
  • Jobs 18
  • Andrew Trenk 13
  • C++ 11
  • Patrik Höglund 8
  • JavaScript 7
  • Allen Hutchison 6
  • George Pirocanac 6
  • Zhanyong Wan 6
  • Harry Robinson 5
  • Java 5
  • Julian Harty 5
  • Adam Bender 4
  • Alberto Savoia 4
  • Ben Yu 4
  • Erik Kuefler 4
  • Philip Zembrod 4
  • Shyam Seshadri 4
  • Chrome 3
  • Dillon Bly 3
  • John Thomas 3
  • Lesley Katzen 3
  • Marc Kaplan 3
  • Markus Clermont 3
  • Max Kanat-Alexander 3
  • Sonal Shah 3
  • APIs 2
  • Abhishek Arya 2
  • Alan Myrvold 2
  • Alek Icev 2
  • Android 2
  • April Fools 2
  • Chaitali Narla 2
  • Chris Lewis 2
  • Chrome OS 2
  • Diego Salas 2
  • Dori Reuveni 2
  • Jason Arbon 2
  • Jochen Wuttke 2
  • Kostya Serebryany 2
  • Marc Eaddy 2
  • Marko Ivanković 2
  • Mobile 2
  • Oliver Chang 2
  • Simon Stewart 2
  • Stefan Kennedy 2
  • Test Flakiness 2
  • Titus Winters 2
  • Tony Voellm 2
  • WebRTC 2
  • Yiming Sun 2
  • Yvette Nameth 2
  • Zuri Kemp 2
  • Aaron Jacobs 1
  • Adam Porter 1
  • Adam Raider 1
  • Adel Saoud 1
  • Alan Faulkner 1
  • Alex Eagle 1
  • Amy Fu 1
  • Anantha Keesara 1
  • Antoine Picard 1
  • App Engine 1
  • Arham Jain 1
  • Ari Shamash 1
  • Arif Sukoco 1
  • Bartosz Papis 1
  • Benjamin Pick 1
  • Bob Nystrom 1
  • Bruce Leban 1
  • Carlos Arguelles 1
  • Carlos Israel Ortiz García 1
  • Cathal Weakliam 1
  • Chris Kennelly 1
  • Christopher Semturs 1
  • Clay Murphy 1
  • Dagang Wei 1
  • Dan Maksimovich 1
  • Dan Shi 1
  • Dan Willemsen 1
  • Dave Chen 1
  • Dave Gladfelter 1
  • David Bendory 1
  • David Mandelberg 1
  • Derek Snyder 1
  • Diego Cavalcanti 1
  • Dmitry Vyukov 1
  • Eduardo Bravo Ortiz 1
  • Ekaterina Kamenskaya 1
  • Elliott Karpilovsky 1
  • Elliotte Rusty Harold 1
  • Espresso 1
  • Felipe Sodré 1
  • Francois Aube 1
  • Gene Volovich 1
  • Google+ 1
  • Goran Petrovic 1
  • Goranka Bjedov 1
  • Hank Duan 1
  • Havard Rast Blok 1
  • Hongfei Ding 1
  • Jason Elbaum 1
  • Jason Huggins 1
  • Jay Han 1
  • Jeff Hoy 1
  • Jeff Listfield 1
  • Jessica Tomechak 1
  • Jim Reardon 1
  • Joe Allan Muharsky 1
  • Joel Hynoski 1
  • John Micco 1
  • John Penix 1
  • Jonathan Rockway 1
  • Jonathan Velasquez 1
  • Josh Armour 1
  • Julie Ralph 1
  • Kai Kent 1
  • Kanu Tewary 1
  • Karin Lundberg 1
  • Kaue Silveira 1
  • Kevin Bourrillion 1
  • Kevin Graney 1
  • Kirkland 1
  • Kurt Alfred Kluever 1
  • Kyle Freeman 1
  • Manjusha Parvathaneni 1
  • Marek Kiszkis 1
  • Marius Latinis 1
  • Mark Ivey 1
  • Mark Manley 1
  • Mark Striebeck 1
  • Matt Lowrie 1
  • Meredith Whittaker 1
  • Michael Bachman 1
  • Michael Klepikov 1
  • Mike Aizatsky 1
  • Mike Wacker 1
  • Mona El Mahdy 1
  • Nimit Khandelwal 1
  • Noel Yap 1
  • Palak Bansal 1
  • Patricia Legaspi 1
  • Per Jacobsson 1
  • Peter Arrenbrecht 1
  • Peter Spragins 1
  • Phil Norman 1
  • Phil Rollet 1
  • Pooja Gupta 1
  • Project Showcase 1
  • Radion Khait 1
  • Radoslav Vasilev 1
  • Rahul Singal 1
  • Rajat Dewan 1
  • Rajat Jain 1
  • Rich Martin 1
  • Richard Bustamante 1
  • Roman Govsheev 1
  • Roshan Sembacuttiaratchy 1
  • Ruslan Khamitov 1
  • Saicharan Nimmala 1
  • Sam Lee 1
  • Sean Jordan 1
  • Sebastian Dörner 1
  • Shahar Roth 1
  • Sharon Zhou 1
  • Shiva Garg 1
  • Siddartha Janga 1
  • Simran Basi 1
  • Stan Chan 1
  • Stephen Ng 1
  • Tejas Shah 1
  • Test Analytics 1
  • Test Engineer 1
  • Tim Lyakhovetskiy 1
  • Tom O'Neill 1
  • Vojta Jína 1
  • Zhe Lu 1
  • automation 1
  • dead code 1
  • iOS 1
  • mutation testing 1


Archive


  • ►  2026 (8)
    • ►  out. (1)
    • ►  jul. (1)
    • ►  jun. (1)
    • ►  mai. (2)
    • ►  abr. (1)
    • ►  mar. (2)
  • ►  2025 (3)
    • ►  out. (1)
    • ►  set. (1)
    • ►  jan. (1)
  • ►  2024 (13)
    • ►  dez. (1)
    • ►  out. (1)
    • ►  set. (1)
    • ►  ago. (1)
    • ►  jul. (1)
    • ►  mai. (3)
    • ►  abr. (3)
    • ►  mar. (1)
    • ►  fev. (1)
  • ►  2023 (14)
    • ►  dez. (2)
    • ►  nov. (2)
    • ►  out. (5)
    • ►  set. (3)
    • ►  ago. (1)
    • ►  abr. (1)
  • ►  2022 (2)
    • ►  fev. (2)
  • ►  2021 (3)
    • ►  jun. (1)
    • ►  abr. (1)
    • ►  mar. (1)
  • ►  2020 (8)
    • ►  dez. (2)
    • ►  nov. (1)
    • ►  out. (1)
    • ►  ago. (2)
    • ►  jul. (1)
    • ►  mai. (1)
  • ►  2019 (4)
    • ►  dez. (1)
    • ►  nov. (1)
    • ►  jul. (1)
    • ►  jan. (1)
  • ►  2018 (7)
    • ►  nov. (1)
    • ►  set. (1)
    • ►  jul. (1)
    • ►  jun. (2)
    • ►  mai. (1)
    • ►  fev. (1)
  • ►  2017 (17)
    • ►  dez. (1)
    • ►  nov. (1)
    • ►  out. (1)
    • ►  set. (1)
    • ►  ago. (1)
    • ►  jul. (2)
    • ►  jun. (2)
    • ►  mai. (3)
    • ►  abr. (2)
    • ►  fev. (1)
    • ►  jan. (2)
  • ►  2016 (15)
    • ►  dez. (1)
    • ►  nov. (2)
    • ►  out. (1)
    • ►  set. (2)
    • ►  ago. (1)
    • ►  jun. (2)
    • ►  mai. (3)
    • ►  abr. (1)
    • ►  mar. (1)
    • ►  fev. (1)
  • ►  2015 (14)
    • ►  dez. (1)
    • ►  nov. (1)
    • ►  out. (2)
    • ►  ago. (1)
    • ►  jun. (1)
    • ►  mai. (2)
    • ►  abr. (2)
    • ►  mar. (1)
    • ►  fev. (1)
    • ►  jan. (2)
  • ►  2014 (24)
    • ►  dez. (2)
    • ►  nov. (1)
    • ►  out. (2)
    • ►  set. (2)
    • ►  ago. (2)
    • ►  jul. (3)
    • ►  jun. (3)
    • ►  mai. (2)
    • ►  abr. (2)
    • ►  mar. (2)
    • ►  fev. (1)
    • ►  jan. (2)
  • ►  2013 (16)
    • ►  dez. (1)
    • ►  nov. (1)
    • ►  out. (1)
    • ►  ago. (2)
    • ►  jul. (1)
    • ►  jun. (2)
    • ►  mai. (2)
    • ►  abr. (2)
    • ►  mar. (2)
    • ►  jan. (2)
  • ►  2012 (11)
    • ►  dez. (1)
    • ►  nov. (2)
    • ►  out. (3)
    • ►  set. (1)
    • ►  ago. (4)
  • ►  2011 (39)
    • ►  nov. (2)
    • ►  out. (5)
    • ►  set. (2)
    • ►  ago. (4)
    • ►  jul. (2)
    • ►  jun. (5)
    • ►  mai. (4)
    • ►  abr. (3)
    • ►  mar. (4)
    • ►  fev. (5)
    • ►  jan. (3)
  • ►  2010 (37)
    • ►  dez. (3)
    • ►  nov. (3)
    • ►  out. (4)
    • ►  set. (8)
    • ►  ago. (3)
    • ►  jul. (3)
    • ►  jun. (2)
    • ►  mai. (2)
    • ►  abr. (3)
    • ►  mar. (3)
    • ►  fev. (2)
    • ►  jan. (1)
  • ►  2009 (54)
    • ►  dez. (3)
    • ►  nov. (2)
    • ►  out. (3)
    • ►  set. (5)
    • ►  ago. (4)
    • ►  jul. (15)
    • ►  jun. (8)
    • ►  mai. (3)
    • ►  abr. (2)
    • ►  fev. (5)
    • ►  jan. (4)
  • ▼  2008 (75)
    • ►  dez. (6)
    • ►  nov. (8)
    • ►  out. (9)
    • ►  set. (8)
    • ►  ago. (9)
    • ►  jul. (9)
    • ►  jun. (6)
    • ▼  mai. (6)
      • Performance Testing of Distributed File Systems at...
      • TotT: The Invisible Branch
      • Intro to Ad Quality Test Challenges
      • Exploratory Testing on Chat
      • TotT: Using Dependancy Injection to Avoid Singletons
      • TotT: Testable Contracts Make Exceptional Neighbors
    • ►  abr. (4)
    • ►  mar. (4)
    • ►  fev. (4)
    • ►  jan. (2)
  • ►  2007 (41)
    • ►  out. (6)
    • ►  set. (5)
    • ►  ago. (3)
    • ►  jul. (2)
    • ►  jun. (2)
    • ►  mai. (2)
    • ►  abr. (7)
    • ►  mar. (5)
    • ►  fev. (5)
    • ►  jan. (4)

Feed

  • Google
  • Privacy
  • Terms