-1

I am reading the book TDD by Example and one of the patterns demonstrated was the self-shunt pattern.

Basically, if I am not mistaken, if I have a test like this:

test("list of users should receive a new user"), () => {
  const user = new User()
  const listOfUsers = new ListOfUsers()
  listOfUsers.insert(user)
}

Then, the only way to know if listOfUsers actually received the user, is to stub it, correct?

class ListOfUsersStub {
  constructor () {
    this.users = []
  }

  insert (user) {
    this.users.push(user)
    return this.users
  }
}

then I can test it so:

test("list of users should receive a new user"), () => {
  const user = new User()
  const listOfUsers = new ListOfUsersStub()
  const result = listOfUsers.insert(user)
  expect(result.users).toContain(user)
}

Is this the same as the self shunt pattern? Or am I missing something?

Thanks

1
  • "the only way to know if listOfUsers actually received the user, is to stub it, correct?" - if listOfUsers is designed reasonably and provides a way to retrieve the objects it contains, then the answer is no, that's plain wrong.
    – Doc Brown
    Jun 15 '20 at 5:37
4

No, your example does not show the self-shunt pattern.

The self-shunt pattern can only be implemented with testing frameworks where the testcases are either a class or a method within an explicitly defined class. The bottom-line is that you must write that class. It cannot come from the testing framework.

A second requirement for the self-shunt pattern is that the code-under-test wants to use a dependency that can be injected. In the self-shunt pattern, it is the testcase class itself, augmented to implement the right interface, that gets injected for that dependency.


Then, the only way to know if listOfUsers actually received the user, is to stub it, correct?

No. And most emphatically no if ListOfUsers is the class you are actually testing.

With a stub, you replace a class that does something complicated, time-consuming or otherwise problematic for stable, repeatable tests with a class that just returns canned answers according to your testing needs. You do not want to do such a replacement of the very code you are trying to establish of that is works correctly.

The correct way to know in insertion into listOfUsers worked is to check if listOfUsers contains the new element. This is one example why the unit you are testing is the entire class, rather than a single method and why a unittest can call multiple methods of a class and still be properly called a unittest.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.