Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Yep. The issue with tests that are heavy on interfaces and mocks is that they are "too close" to the code - if refactoring is changing code while tests stay green, how can you refactor when any change to any method breaks a test?

Swapping out interfaces to code-gened interceptors and keeping everything else the same, doesn't look like it would improve this underlying issue at all.



> how can you refactor when any change to any method breaks a test

You fix until tests pass. How do you know you adjusted all tests when code changes and tests stay green?


The real problem is you are testing the class behaves like the class, but not the business-driven requirements. Therefore refactoring becomes fearful since detecting bugs is no longer the job of tests.


A business model can be described in code as an integration test. Wouldn’t an integration test work in that case?


> A business model can be described in code as an integration test.

A business case can be described in code as a test. Period.

A small unit of business functionality can be described in code as test that tests that "unit". A unit test, if you will.

I don't think that the way that you're dividing out "integration tests" is a useful one.

> Wouldn’t an integration test work in that case?

Wouldn’t a test work in that case? Well, yes.


Yes, depending on what you mean by integration test.

It is nuanced subject.

But say you have class A,B,C,D with mocked dependencies E,F,G,H.

There could be bugs in how A interacts with E and F that are hidden even though you have tests for A,B,C,D integrated and even unit tests on E too.

In addition, if someone comes along and refactors A,B,C,D into A',B',C',D' that have different dependencies ("Hey we are moving to microservices!") then the new integration test is different. You change test and code at the same time.

This is a problem because confidence comes from having a stable test, then changing the code and getting the green circles.

The solution (I think) is to make sure you are mocking at the level of well established boundaries. For example mock PostgreSQL. Or mock your ORM if there is a decent mock, with an in-memory version.

Then you can test end-to-end scenarios. Add a TODO, add another TODO, assert that getTodos() returns 2 results, and so on.

Instead of assert getTodos() returns 2 results when the ITodoService.getTodos() returns 2 results, and the outer getTodos just defers to it.


If the parent comment is also saying "If a test describes a business requirement rather than a class and method, then it must be an integration test"

Then I think that parent is wrong, or rather that "it depends on what you mean by integration test" an further, this definition of "integration test" is an extremely unhelpful one that I do not advise using. And it better fits what was originally intended as "unit test". The name "unit" is not a synonym for class or method, it is your choice what the "unit" is, and a lot of the time it is best done as a small chunk of business requirement.

mocking at the level of well established boundaries such as databases and http services, is all that's needed.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: