Dennis van der Stelt

The only way to win is to learn faster than anyone else

Community

Email Notifications

News

  • Addicted to Refactor! Pro

I read...

I Use...

Tags

Recent Posts

Archives

Blog Subscription Form

  • Email Notifications
    Go

April 2009 - Posts

DevDays wildcard proposals and voting

Because it’s not clear to anyone, I want to state that you don’t have to actually be a visitor of the DevDays to be able to vote on the sessions. The only thing you need to do is register for an account, verify your email address by clicking on the link in the email you receive and you’re allowed to vote. Don’t forget to vote for my session.

Almost all companies use a source control repository to work in a team, but a lot of those don’t use Continuous Integration (CI) to…

  • Commit code at least once a day
  • Verify everything still works by running unit tests on an integration machine
  • Deploy databases and set up test databases for integration tests
  • Create deployment packages for test, acceptance and production environments
  • Be able to verify what the status of the project is
  • Deploy any day, any time

That’s what I want to explain and show during the developer days. If you want to know more about this, vote for my session.

Dennis Doomen will also be able to present you with a great presentation on Test-Driven Development and SOLID principles by Robert C. Martin (Uncle Bob) if you vote for him too.

On a site note, it’s funny how I sometimes see the ranking of both sessions drop. Some people seem to vote on a friend or colleague and give a thumb down on my and Dennis Doomen his session. Although it might be tempting to make all our thumb up voters also give a thumb down to all other sessions, it’s also a pretty sad. So giving me the thumb up will do, thank you. :-)

Asserting private objects with unit testing

There’s a lot of discussion going on about designing for testability. One of the problems of unit testing your code is that you might want to insert a fake object (like a stub or mock) so that your code under test won’t actually call out to the database or an external logging class. You can solve this by Inversion of Control (IoC) and using Dependency Injection (DI). You insert an object you want to isolate or an object you want to do assertions on via the constructor or properties.

Typemock Isolator also has a very powerful feature where you don’t have to use dependency injection. Let me be clear on this before you continue reading : you don’t have to. I know with Isolator you might not even need DI but it’s still a good practice to decouple dependencies. But I personally think it’s a bit sad that you need to change your design and use DI just because else you would not be able to write your test. And that’s where Isolator can help us.

Imagine we have to following code. A class called “SomeClass” with a method called “SomeMethod” that we want to test. This method however creates an instance of the “ClassWithProperties” class. Our method will fill this object and we really want to see what happened with this object. We want to verify it using tests. We’ve got different tests to test “ClassWithProperties”, but we want to know if the few lines of code that work with this extra class is doing what we expect it to do.

public class SomeClass
{
    public void SomeMethod(string name, int age)
    {
        ClassWithProperties cwp = new ClassWithProperties();
        cwp.Name = name;
        cwp.Age = age;

        // Start processing, calling ServiceAgents, whatever...
    }
}

public class ClassWithProperties
{
    public string Name { get; set; }
    public int Age { get; set; }
}

A real life example of this, for me at least, was where an Order object was created and filled with order lines and customer information and I wanted to assert the flow inside the method and if the object was filled correctly. Was the Order object indeed filled with the correct information?

We can insert the ClassWithProperties object via DI or use a ServiceLocator but why do that if you have a powerful framework? Using Reflective Mocks, the ‘old’ way (since there’s a much better API now) we could do the following.

[TestMethod]
public void CanWeGrabInternalObject()
{
    // Arrange
    string name = "Dennis";
    int age = 34;

    Mock mockedClassWithProperties = MockManager.Mock<ClassWithProperties>();

    // Act
    new SomeClass().SomeMethod(name, age);

    // Assert
    var result = mockedClassWithProperties.MockedInstance as ClassWithProperties;
    Assert.AreEqual(name, result.Name);
    Assert.AreEqual(age, result.Age);
}

What you see here is that a Mock object is created at line 8, which could be described as a fake version of our ClassWithProperties. We then make the call to “SomeMethod” at line 11 and pass two arguments that is mapped onto the class that’s created inside “SomeClass”. However using MockManager.Mock we make sure future instances are replaced by our fake object. When the call to “SomeMethod” is done we can retrieve the instance that our fake object is at line 14. We can then easily assert its current state and see if everything was correct. The Reflective Mocks is however not the most easiest way to go, although it’s still very powerful.

The Triple-A or ArrangeActAssert API is since Isolator 5.0 the way to go because of cleaner unit tests and its API is also much easier to understand. In our example we’d get the following result.

[TestMethod]
public void CanWeGrabInternalObjectWithNewAPI()
{
    // Arrange
    string name = "Alex";
    int age = 37;

    var fake = Isolate.Fake.Instance<ClassWithProperties>();
    Isolate.Swap.NextInstance<ClassWithProperties>().With(fake);

    // Act
    new SomeClass().SomeMethod(name, age);

    // Assert
    Assert.AreEqual(name, fake.Name);
    Assert.AreEqual(age, fake.Age);    
}

In line 8 we create the fake instance but nothing happens with future instances. If we’d use DI we could inject our fake object. As we’re not, in line 9 we’re making sure the next instance that’s created is swapped with our fake object. As you can see this is exactly the same behavior as the first test we wrote, but it’s much more clearer on what’s happening. We then call “SomeMethod” and make the same assertions.

However we’re now interfering with everything that’s normal to this ClassWithProperties. Constructor and other methods aren’t called. When we do want the class to act as usual, ie. be able to execute methods on it, we need a different approach. The "Isolate.Fake.Instance” method has an overload that allows us to supply an argument what the fake object should actually do. We can use Members.CallOriginal on it to make it behave like before. However that will also destroy our ability to check the state of the swapped object.

This is where we can perform a little trick though. Now that we have access to our fake object, we can redirect every call to this fake object to an object of our liking. We don’t even have to use a fake object. Hence the following test.

[TestMethod]
public void CanGrabFakedObjectAndRedirectCalls()
{
    // Arrange
    string name = "Marco";
    int age = 33;

    var fake = Isolate.Fake.Instance<ClassWithProperties>(Members.CallOriginal);
    var original = new ClassWithProperties();
    Isolate.Swap.NextInstance<ClassWithProperties>().With(fake);
    Isolate.Swap.CallsOn(fake).WithCallsTo(original);
    

    // Act
    new SomeClass().SomeMethod(name, age);

    // Assert
    Assert.AreEqual(name, original.Name);
    Assert.AreEqual(age, original.Age);            
}

Here you see that with the creation of the fake “ClassWithProperties” object, we specify that we actually want to call the original object. You normally do this, for example, when you want to verify specific calls on the object, set expectations on only a few method calls and/or want to redirect one or more calls. And that’s what we do, but we’re redirecting all calls. And we redirect them to the variable we call “original” in this test.

This will make sure, everything that’s happening on the fake object will get redirected to the object that we initialized, maintain and eventually assert in our test. Again, simple state based testing, although less elegant than the first test with reflective mocks.

Now of course there’s also a different way and speaking of elegant code, this is also technically better. And although I love state based testing over verifications (because most of the time it’s more readable), this last test is probably the nicest there is right now.

[TestMethod]
public void UseVerificationsOnObject()
{
    // Arrange
    string name = "Mike";
    int age = 35;

    var fake = Isolate.Fake.Instance<ClassWithProperties>(Members.CallOriginal);
    Isolate.Swap.NextInstance<ClassWithProperties>().With(fake);

    // Act
    new SomeClass().SomeMethod(name, age);

    // Assert
    Isolate.Verify.WasCalledWithExactArguments(() => fake.Name = name);
    Isolate.Verify.WasCalledWithExactArguments(() => fake.Age = age);
}

As a conclusion, there seem to be a lot of options with Typemock Isolator. Two remarks have to be made here. First of all, Isolator is so powerful that sometimes problems can have multiple solutions to it. This isn’t always what you want, as this makes finding the best solution harder. Especially when you don’t know what the best solution is, even though you know all possible solutions. Luckily with the new AAA API it’s much more clearer on what path to take.

As a second, for these tests, I’d say the last one is the best, because it’s best at revealing all the intention, one of my favorite rules of TDD by Kent Beck in his Extreme Programming Explained.

Wildcard proposal : If you build it, you’ll ship it

Every developer is familiar with the phrase "It works on my machine". But what if you could claim your code can be deployed at any time of the day? Simply because the latest tested and verified version has been prepared for you on your build server. Not to mention with separate installation packages for both testing-, acceptance and production environment?

If you would like to know how you can set up such an environment using the best tools and the best practices, vote for me at the DevDays site and let me tell my story in one of the two wildcard sessions.

I’m going to be talking about how to setup a build and use continuous integration to build the code, verify all unit tests and integration tests, build packages for all different environments and servers and setup configuration for each of them. We’ll do this using Team Foundation Server, MSBuild, FinalBuilder and more and also list a lot of the common tools used. Also discussed will be how to setup each environment and how virtualization can help you set these up. After visiting this session, you’ll know the best practices but also some of the anti patterns of continuous integration.

And if you want to know how you can get cake at work, every day, vote for my session and some see it.