How to TDD test that objects are being added to a collection if the collection is private?

Assume that I planned to write a class that worked something like this:

public class GameCharacter {
    private Collection<CharacterEffect> _collection;

    public void Add(CharacterEffect e) { ... }
    public void Remove(CharacterEffect e) { ... }
    public void Contains(CharacterEffect e) { ... }
}

When added an effect does something to the character and is then added to the _collection. When it is removed the effect reverts the change to the character and is removed from the _collection.

It’s easy to test if the effect was applied to the character, but how do I test that the effect was added to _collection?

What test could I write to start constructing this class. I could write a test where Contains would return true for a certain effect being in _collection, but I can’t arrange a case where that function would return true because I haven’t implemented the Add method that is needed to place things in _collection.

Ok, so since Contains is dependent on having Add working, then why don’t I try to create Add first. Well for my first test I need to try and figure out if the effect was added to the _collection. How would I do that? The only way to see if an effect is in _collection is with the Contains function.

The only way that I could think to test this would be to use a FakeCollection that Mocks the Add, Remove, and Contains of a real collection, but I don’t want _collection being affected by outside sources. I don’t want to add a setEffects(Collection effects) function, because I do not want the class to have that functionality. The one thing that I am thinking could work is this:

public class GameCharacter<C extends Collection> {
    private Collection<CharacterEffect> _collection;

    public GameCharacter() {
        _collection = new C<CharacterEffect>();
    }
}

But, that is just silly making me declare what some private data structures type is on every declaration of the character.

Is there a way for me to test this without breaking TDD principles while still allowing me to keep my collection private?

2

The confusion you are having here is because you are trying to write a test about the implementation details, not about the desired effect. Thinking instead about the desired behaviors of the class is likely to lead you to a better test.

In this example, it seems to me you have two behaviors you want to test:

  • When added an effect does something to the character
  • When it is removed the effect reverts the change to the character

I’m not exactly sure what a character effect is, but here’s an example test that makes a fairly reasonable assumption, and hopefully gets my point across even if it’s a little off:

[Test]
public void AddAndRemovingEffectsAltersCharachterAppropriately()
{
    var originalStrength = _character.Strength;
    CharacterEffect strengthPotion = new StrengthPotion();
    _character.Add(strengthPotion);
    Assert.That(_character.Strength, Is.GreaterThan(originalStrength));

    //normally I'd make a second test for this, 
    //but the answer edit box is not a great IDE  :)
    _character.Remove(strengthPotion);
    Assert.That(_character.Strength, Is.EqualTo(originalStrength));
}

Notice: this test doesn’t care about the collection at all. It’s not obvious from reading it that a collection is necessary. The collection is merely an implementation detail. It’s beneath the notice of the test.

Side note: The “add” and “remove” names for methods do suggest a collection, and don’t really communicate that domain relevant purpose of the methods. I’d prefer something like Apply or Consume over Add. Or perhaps character.Inventory.Add() if we are talking about equipment.

3

You seem to understand the incremental part of TDD, that is to implement the smallest possible functionality at a time. However, there are cases like the one you are facing that make it extremely difficult to do. In your particular situation, I would not bother trying to implement them separatly and I would implement Add and Contains at the same time.

The typical TDD cycle starts with : Write your test and make it compile. In your case, your test would look like so :

var g = new GameCharacter();
var c = new CharacterEffect();
g.Add(c);
Assert.That(g.Contains(c));

In order to make your test compile (step 2), you have to implement both Add and Contains, which I think is perfectly fine. TDD says that you should take the smallest step possible, and this seems to be the smallest you can do. You don’t need to go crazy about implementing every method individually or you will likely hit the same walls again and again.

1

It’s easy to test if the effect was applied to the character, but how do I test that the effect was added to _collection?

You shouldn’t.

You need to ask why it matters that an item is added to the collection. “Well, it should then have a certain effect on the character.” Then test for that effect. There isn’t any value in testing that a rudimentary collection works as a collection.

And suppose someday you modify the program to create character effects in a very different way. If you test that your collection works, your test becomes useless when you get rid of the collection. But if you test for character effects, your test will still work with a different code mechanism. That’s as it should be; you need to test that your program works correctly, not that your programming language works correctly.

Have a look at this answer, by Kent Beck, about what one should test:

How deep are your unit tests?

I get paid for code that works, not for tests, so my philosophy is to test as little as possible to reach a given level of confidence…If I don’t typically make a kind of mistake (like setting the wrong variables in a constructor), I don’t test for it.

Unless you’re completely unfamiliar with the programming language you’re using or with a library you’re using, it just doesn’t make sense to test that a collection works as a collection, or that you can create a new object, or that a variable is incremented when you tell it to increment.

All you’re doing in such cases is making sure your programming language works as it’s designed to, which is generally not a thing you’d have to test unless you’re the one designing the language.

You shouldn’t test classes but interfaces where by interface, beside the typical meaning, you could also understand the signatures of the public methods of a class. Your classes should adhere to strong contracts; from the testing point of view (and from other clients’ POV) you shouldn’t care how those contracts are respected/implemented.

In your particular case there is a problem with your class design; your add method does two things: firstly it changes the CharacterEffect and then it adds that object to the collection of character effects. This bad design decision makes it difficult to test!

If you really want to see a private field, you can use reflection, but that is not an orthodox way of doing things.

Have your unit tests be implemented in a friend class.

That lets you poke into private and protected stuff freely for the purposes of the unit test without having to make it part of the external API.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật