Reputation: 536
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?
Upvotes: 5
Views: 4113
Reputation: 7302
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.
Upvotes: 1
Reputation: 41965
new
operator yourself will be enough! This means tightly coupled code which is your answer.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;
}
}
Upvotes: 1
Reputation: 11775
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:
Upvotes: 5
Reputation: 1231
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.
Upvotes: 1
Reputation: 37576
Well some answers could be
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.
Upvotes: 2