├── .classpath
├── .gitignore
├── .project
├── .settings
├── org.eclipse.jdt.core.prefs
└── org.maven.ide.eclipse.prefs
├── README.markdown
├── pom.xml
└── src
├── main
└── java
│ └── org
│ └── craftedsw
│ └── harddependencies
│ ├── TripService_Original.java
│ ├── exception
│ ├── DependendClassCallDuringUnitTestException.java
│ └── UserNotLoggedInException.java
│ ├── trip
│ ├── Trip.java
│ ├── TripDAO.java
│ └── TripService.java
│ └── user
│ ├── User.java
│ └── UserSession.java
└── test
└── java
└── org
└── craftedsw
└── harddependencies
├── TripServiceTest.java
├── UserBuilder.java
└── UserTest.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | legacy-harddependencies
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.maven.ide.eclipse.maven2Builder
15 |
16 |
17 |
18 |
19 |
20 | org.maven.ide.eclipse.maven2Nature
21 | org.eclipse.jdt.core.javanature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | #Wed Jun 29 02:14:55 BST 2011
2 | eclipse.preferences.version=1
3 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
4 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
5 | org.eclipse.jdt.core.compiler.compliance=1.6
6 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
7 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
8 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
9 | org.eclipse.jdt.core.compiler.source=1.6
10 |
--------------------------------------------------------------------------------
/.settings/org.maven.ide.eclipse.prefs:
--------------------------------------------------------------------------------
1 | #Wed Jun 29 01:48:09 BST 2011
2 | activeProfiles=
3 | eclipse.preferences.version=1
4 | fullBuildGoals=process-test-resources
5 | resolveWorkspaceProjects=true
6 | resourceFilterGoals=process-resources resources\:testResources
7 | skipCompilerPlugin=true
8 | version=1
9 |
--------------------------------------------------------------------------------
/README.markdown:
--------------------------------------------------------------------------------
1 | Testing legacy code: Hard-wired dependencies
2 | ============================================
3 |
4 | Code related to my [Testing legacy code: Hard-wired dependencies][1] blog post
5 |
6 | What is it about?
7 | -----------------
8 |
9 | Provides an example of existing code that needs to be unit tested. But there is one rule:
10 |
11 | > We can't change any existing code if not covered by tests. The only exception is if we need to change the code to add unit tests, but in this case, just automated refactorings (via IDE) are allowed.
12 |
13 | Although this is a very small piece of code, it has a lot of the problems that we find in legacy code.
14 |
15 | Details
16 | -------
17 |
18 | If you want to give it a go, the starting point is [TripService_Original.java][2]. Try unit testing it following the rule above.
19 |
20 | My solution was [TripServiceTest.java][3] and [TripSerivce.java][4]
21 |
22 | [1]: http://craftedsw.blogspot.com/2011/07/testing-legacy-hard-wired-dependencies.html "Testing legacy code: Hard-wired dependencies blog post"
23 | [2]: https://github.com/sandromancuso/testing_legacy_code/blob/master/src/main/java/org/craftedsw/harddependencies/TripService_Original.java "TripService_Original.java"
24 | [3]: https://github.com/sandromancuso/testing_legacy_code/blob/master/src/test/java/org/craftedsw/harddependencies/TripServiceTest.java "TripServiceTest.java"
25 | [4]: https://github.com/sandromancuso/testing_legacy_code/blob/master/src/main/java/org/craftedsw/harddependencies/trip/TripService.java "TripService.java"
26 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | org.craftedsw
5 | legacy-harddependencies
6 | 0.0.1-SNAPSHOT
7 | legacy-harddependencies
8 |
9 |
10 |
11 | org.hamcrest
12 | hamcrest-all
13 | 1.1
14 | test
15 |
16 |
17 | junit
18 | junit
19 | 4.8.2
20 | test
21 |
22 |
23 | org.mockito
24 | mockito-all
25 | 1.8.5
26 | test
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/main/java/org/craftedsw/harddependencies/TripService_Original.java:
--------------------------------------------------------------------------------
1 | package org.craftedsw.harddependencies;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import org.craftedsw.harddependencies.exception.UserNotLoggedInException;
7 | import org.craftedsw.harddependencies.trip.Trip;
8 | import org.craftedsw.harddependencies.trip.TripDAO;
9 | import org.craftedsw.harddependencies.user.User;
10 | import org.craftedsw.harddependencies.user.UserSession;
11 |
12 | public class TripService_Original {
13 |
14 | public List getTripsByUser(User user) throws UserNotLoggedInException {
15 | List tripList = new ArrayList();
16 | User loggedUser = UserSession.getInstance().getLoggedUser();
17 | boolean isFriend = false;
18 | if (loggedUser != null) {
19 | for (User friend : user.getFriends()) {
20 | if (friend.equals(loggedUser)) {
21 | isFriend = true;
22 | break;
23 | }
24 | }
25 | if (isFriend) {
26 | tripList = TripDAO.findTripsByUser(user);
27 | }
28 | return tripList;
29 | } else {
30 | throw new UserNotLoggedInException();
31 | }
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/org/craftedsw/harddependencies/exception/DependendClassCallDuringUnitTestException.java:
--------------------------------------------------------------------------------
1 | package org.craftedsw.harddependencies.exception;
2 |
3 | public class DependendClassCallDuringUnitTestException extends RuntimeException {
4 |
5 | private static final long serialVersionUID = -4584041339906109902L;
6 |
7 | public DependendClassCallDuringUnitTestException() {
8 | super();
9 | }
10 |
11 | public DependendClassCallDuringUnitTestException(String message,
12 | Throwable cause) {
13 | super(message, cause);
14 | }
15 |
16 | public DependendClassCallDuringUnitTestException(String message) {
17 | super(message);
18 | }
19 |
20 | public DependendClassCallDuringUnitTestException(Throwable cause) {
21 | super(cause);
22 | }
23 |
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/org/craftedsw/harddependencies/exception/UserNotLoggedInException.java:
--------------------------------------------------------------------------------
1 | package org.craftedsw.harddependencies.exception;
2 |
3 | public class UserNotLoggedInException extends Exception {
4 |
5 | private static final long serialVersionUID = 8959479918185637340L;
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/org/craftedsw/harddependencies/trip/Trip.java:
--------------------------------------------------------------------------------
1 | package org.craftedsw.harddependencies.trip;
2 |
3 | public class Trip {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/org/craftedsw/harddependencies/trip/TripDAO.java:
--------------------------------------------------------------------------------
1 | package org.craftedsw.harddependencies.trip;
2 |
3 | import java.util.List;
4 |
5 | import org.craftedsw.harddependencies.exception.DependendClassCallDuringUnitTestException;
6 | import org.craftedsw.harddependencies.user.User;
7 |
8 | public class TripDAO {
9 |
10 | public static List findTripsByUser(User user) {
11 | throw new DependendClassCallDuringUnitTestException(
12 | "TripDAO should not be invoked on an unit test.");
13 | }
14 |
15 | }
--------------------------------------------------------------------------------
/src/main/java/org/craftedsw/harddependencies/trip/TripService.java:
--------------------------------------------------------------------------------
1 | package org.craftedsw.harddependencies.trip;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import org.craftedsw.harddependencies.exception.UserNotLoggedInException;
7 | import org.craftedsw.harddependencies.user.User;
8 |
9 | public class TripService {
10 |
11 | public List getFriendTrips(User loggedUser, User friend) throws UserNotLoggedInException {
12 | validate(loggedUser);
13 | return (friend.isFriendsWith(loggedUser))
14 | ? findTripsForFriend(friend)
15 | : new ArrayList();
16 | }
17 |
18 | private void validate(User loggedUser) throws UserNotLoggedInException {
19 | if (loggedUser == null) throw new UserNotLoggedInException();
20 | }
21 |
22 | protected List findTripsForFriend(User friend) {
23 | return TripDAO.findTripsByUser(friend);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/org/craftedsw/harddependencies/user/User.java:
--------------------------------------------------------------------------------
1 | package org.craftedsw.harddependencies.user;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import org.craftedsw.harddependencies.trip.Trip;
7 |
8 | public class User {
9 |
10 | private List trips = new ArrayList();
11 | private List friends = new ArrayList();
12 |
13 | public List getFriends() {
14 | return friends;
15 | }
16 |
17 | public void addFriend(User user) {
18 | friends.add(user);
19 | }
20 |
21 | public boolean isFriendsWith(User friend) {
22 | return friends.contains(friend);
23 | }
24 |
25 | public void addTrip(Trip trip) {
26 | trips.add(trip);
27 | }
28 |
29 | public List trips() {
30 | return trips;
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/org/craftedsw/harddependencies/user/UserSession.java:
--------------------------------------------------------------------------------
1 | package org.craftedsw.harddependencies.user;
2 |
3 | import org.craftedsw.harddependencies.exception.DependendClassCallDuringUnitTestException;
4 |
5 | public class UserSession {
6 |
7 | private static final UserSession userSession = new UserSession();
8 |
9 | private UserSession() {
10 | }
11 |
12 | public static UserSession getInstance() {
13 | return userSession;
14 | }
15 |
16 | public boolean isUserLoggedIn(User user) {
17 | throw new DependendClassCallDuringUnitTestException(
18 | "UserSession.isUserLoggedIn() should not be called in an unit test");
19 | }
20 |
21 | public User getLoggedUser() {
22 | throw new DependendClassCallDuringUnitTestException(
23 | "UserSession.getLoggedUser() should not be called in an unit test");
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/test/java/org/craftedsw/harddependencies/TripServiceTest.java:
--------------------------------------------------------------------------------
1 | package org.craftedsw.harddependencies;
2 |
3 | import static org.craftedsw.harddependencies.UserBuilder.anUser;
4 | import static org.hamcrest.Matchers.equalTo;
5 | import static org.hamcrest.core.Is.is;
6 | import static org.junit.Assert.assertThat;
7 | import static org.junit.Assert.assertTrue;
8 |
9 | import java.util.List;
10 |
11 | import org.craftedsw.harddependencies.exception.UserNotLoggedInException;
12 | import org.craftedsw.harddependencies.trip.Trip;
13 | import org.craftedsw.harddependencies.trip.TripService;
14 | import org.craftedsw.harddependencies.user.User;
15 | import org.junit.Before;
16 | import org.junit.Test;
17 |
18 | public class TripServiceTest {
19 |
20 | private User NON_LOGGED_USER = null;
21 | private User UNUSED_USER = new User();
22 | private User LOGGED_USER = new User();
23 |
24 | private TripService tripService;
25 |
26 | @Before
27 | public void initialise() {
28 | tripService = createTripService();
29 | }
30 |
31 | @Test(expected = UserNotLoggedInException.class) public void
32 | shouldThrowExceptionIfUserIsNotLoggedIn() throws Exception {
33 | tripService.getFriendTrips(NON_LOGGED_USER, UNUSED_USER);
34 | }
35 |
36 | @Test public void
37 | shouldNotReturnTripsWhenLoggedUserIsNotAFriend() throws Exception {
38 | List friendTrips = tripService.getFriendTrips(LOGGED_USER, anUser().build());
39 |
40 | assertTrue(friendTrips.isEmpty());
41 | }
42 |
43 | @Test public void
44 | shouldReturnTripsWhenLoggedUserIsAFriend() throws Exception {
45 | User john = anUser().friendsWith(LOGGED_USER)
46 | .withTrips(new Trip(), new Trip())
47 | .build();
48 |
49 | List friendTrips = tripService.getFriendTrips(LOGGED_USER, john);
50 |
51 | assertThat(friendTrips, is(equalTo(john.trips())));
52 | }
53 |
54 | private TripService createTripService() {
55 | return new TripService() {
56 | @Override protected List findTripsForFriend(User user) {
57 | return user.trips();
58 | }
59 | };
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/test/java/org/craftedsw/harddependencies/UserBuilder.java:
--------------------------------------------------------------------------------
1 | package org.craftedsw.harddependencies;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.List;
6 |
7 | import org.craftedsw.harddependencies.trip.Trip;
8 | import org.craftedsw.harddependencies.user.User;
9 |
10 | public class UserBuilder {
11 |
12 | List friends = new ArrayList();
13 | List trips = new ArrayList();
14 |
15 | public static UserBuilder anUser() {
16 | return new UserBuilder();
17 | }
18 |
19 | public UserBuilder friendsWith(User friend) {
20 | friends.add(friend);
21 | return this;
22 | }
23 |
24 | public UserBuilder withTrips(Trip... trips) {
25 | this.trips.addAll(Arrays.asList(trips));
26 | return this;
27 | }
28 |
29 | public User build() {
30 | User user = new User();
31 | addFriends(user);
32 | addTrips(user);
33 | return user;
34 | }
35 |
36 | private void addTrips(User user) {
37 | for (Trip trip : trips) {
38 | user.addTrip(trip);
39 | }
40 | }
41 |
42 | private void addFriends(User user) {
43 | for (User friend : friends) {
44 | user.addFriend(friend);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/test/java/org/craftedsw/harddependencies/UserTest.java:
--------------------------------------------------------------------------------
1 | package org.craftedsw.harddependencies;
2 |
3 | import static org.junit.Assert.assertTrue;
4 |
5 | import org.craftedsw.harddependencies.user.User;
6 | import org.junit.Test;
7 |
8 | public class UserTest {
9 |
10 | @Test public void
11 | shouldReturnTrueWhenUsersAreFriends() throws Exception {
12 | User John = new User();
13 | User Bob = new User();
14 |
15 | John.addFriend(Bob);
16 |
17 | assertTrue(John.isFriendsWith(Bob));
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------