5

In an interview, I was asked the question “How do you make a code hard to be unit tested?” I ended up mumbling something about writing a tightly coupled code. Can anyone please tell me what’s the right answer/ approach for this question?

Faux Pas
  • 518
  • 7
  • 19

5 Answers5

5

Take a look at Mishko's Guide: Writing Testable Code, introduce as many of these flaws into your code and you'll end up with untestable code.

For example:

  • do as much as you can in constructors, start threads, use loops and ifs
  • break Law of Demeter by creating long chain of method calls
  • use singletons everywhere, never ask for dependencies, look them up in a static provider
  • create god classes with 2k lines of code
denis.solonenko
  • 11,179
  • 2
  • 26
  • 22
2

Well some answers could be

  • a Code which accesses the database
  • a Code which behaves according to the system datetime
  • a Code which does more than one functionality in the same methode (Unit)
  • a Code with a lot of coditional behaviour which depends on another unreadbale code

and in genral any code where it is hard / impossible to simulate the environment in order to let it behave the way which needs to be tested.

CloudyMarble
  • 34,949
  • 69
  • 92
  • 126
  • @NarendraPathai A code is no unittest, the test that tests the code is the unittest, and one should not test units which accesses teh database, so having a logic component which access teh database in a addition to the logic is allmost utnestable and should not be unittested – CloudyMarble Apr 10 '13 at 05:27
  • I meant a test that tries to test a class which access a database will no longer be a unit test and should be called an *integration test*. – Narendra Pathai Apr 10 '13 at 05:30
1
  • Creating dependencies required by a class using new operator yourself will be enough! This means tightly coupled code which is your answer.
  • A code that does not follow SOLID principles.

So in the test you will not be able to use Mock objects as you are creating the dependencies yourself and hardcoding the relationships.

With dependency injection you are able to use polymorphic behavior so the class which is calling some method on the dependency passed to it in constructor or method does not need to know the concrete type. So in testing you can pass a mock object and you will be able to test your class easily.

Misko's Writing testable code explains how we are good at writing code that is not testable and how to solve it.

Example (JAVA):

//hard to unit test this code as testing class A also requires that ClassB should work properly
//What is ClassB does some I/O or DB operations. This makes unit test a integration test
class classA{
   ClassB b = new ClassB();   //Creating concrete dependencies

}

interface B{
     //implemented by Class B and your mock class that you create for testing
}

class ClassA{
     private B b;

     //Here you can use mocking framework or create a mock class yourself and pass that as argument
     //So the mock class will not do any DB or I/O and makes this unit test
     public classA(B b){
         this.b = b;
     }
}
Community
  • 1
  • 1
Narendra Pathai
  • 38,384
  • 18
  • 73
  • 117
1

That is a good answer. Tightly coupled code is extremely hard to unit test (and probably shouldn't be unit tested - it should be re-factored first), because by definition unit tests can only test a specific unit of something. All calls to databases or other components of the system should be avoided from Unit Tests because they violate this.

With that said you could also mention that Integration Tests are good for testing larger couplings of code or code with dependencies, or even behavior based actions. You can build an integration test suite for something like testing your REST API which has many dependencies and even crosses many technologies and multiple programming languages.

Also by not thinking through a design or not using a decent design pattern can lead to extremely coupled or dependent code which can be difficult or impossible to unit test without re-factoring or re-writing. You could then talk about TDD (Test Driven Development http://en.wikipedia.org/wiki/Test-driven_development) or BDD (Behavioral Driven Development http://en.wikipedia.org/wiki/Behavior-driven_development) which forces you to start by designing the test suite and working from there.

Lucas
  • 1,221
  • 9
  • 10
0

Code that's hard to separate - multiple responsibilities spread out between multiple classes, but no class that fully holds any responsibility

Code that's very complex to look at - try the average state machine's if/then/else bomb of 500 lines.

Code that's very strongly in a given field, Mathematics is an obvious example. Take a Fourier transform function and add a single unit test that shows all-zeroes are transformed into all-zeroes. 100% coverage but nothing really tested at all.

Code that's coupled strongly with external dependencies that are intricately linked.

Code with huge interfaces that do multiple things.

dascandy
  • 6,916
  • 1
  • 25
  • 49