Please make PageData.LinkURL virtual – Or why Joe can't sleep

Joe is building a website using EPiServer CMS. As he’s a curious fellow he’s decided to give test driven development a try.

Let's say Joe creates an abstraction of DataFactory.

Also, let's assume that Joe creates a really nice fluent API for creating PageData objects for using when testing.

Further, let's also say that Joe uses the MVP pattern.

Finally, Joe writes a unit test that simply checks that a presenter displays links to children of the start page.

Joe writes the test and it fails as expected. Joe goes on to implement code that satisfies the test. Joe is excited.

Only the test doesn't pass. All that adrenaline that has been built up in Joe. That rush. It's all gone in an instant. Joe stares at the screen. There he reads:

System.TypeInitializationException: The type initializer for 'EPiServer.DataFactory' threw an exception. ---> System.ArgumentException: The application relative virtual path '~/' is not allowed here.

Finally Joe realizes that PageData.LinkURL must be calling DataFactory. Hopeful, Joe goes on to stub out that behavior.

Alas, his screen still reads:

System.TypeInitializationException: The type initializer for 'EPiServer.DataFactory' threw an exception. ---> System.ArgumentException: The application relative virtual path '~/' is not allowed here.

It turns out PageData.LinkURL isn't virtual.

On the outside, Joe's colleagues watches when Joe bravely creates a public virtual method on his presenter that returns the link URL for a PageData object and then goes on to create a partial mock of his presenter.

On the inside he's crying.

Later that night, as he's trying to fall asleep he just can't help but think about the days' events. He remembers Anders Hejlsberg saying "The pragmatic school of thought, which comes from building real applications that run in the real world, says, 'We've got to be real careful about what we make virtual'".

Doesn't Joe live in the real world? Is that's what Anders is saying? Is there something wrong with Joe? Perhaps he wasn't meant to write well designed code. Code that he can be proud of.

Then he thinks back to reading Michael Feathers words. At least he's not alone.

Exhausted Joe finally falls asleep. Tomorrow a brave new day awaits.

As usual the name of the boy in the story isn't his real name.

Also, Joe isn’t really creating any fluent API’s for creating PageData objects, but it might be a good idea for him to keep an eye on what happens in the trunk for EPiAbstractions :)

PS. For updates about new posts, sites I find useful and the occasional rant you can follow me on Twitter. You are also most welcome to subscribe to the RSS-feed.

Comments

  1. Patrik Akselsson's avatar

    Patrik Akselsson 1 years ago

    I think Joe should have a look inside PageData with reflector. Then he migth be get the idea to write code like:

            public PageBuilder WithUrl(string url)
            {
                _page.Property["PageLinkUrl"] = new PropertyString(url);
                return this;
            }
    
  2. Joel Abrahamsson's avatar

    Joel Abrahamsson 1 years ago

    Patrik,

    I talked to Joe and he said that the problem wasn't with setting the value but with retrieving it. That is the SUT should use page.LinkURL to populate a view model. He says he would love ideas on better ways to solve that that doesn't involve stubbing out methods in the presenter or components injected into the presenter though.

  3. Patrik Akselsson's avatar

    Patrik Akselsson 1 years ago

    Ah, we managed to get rid of the type initialization exception and a few other wierd errors by doing a lot of funky stuff in a EPiTestHelper class.

    I do think that the fact that a EPiTestHelper is needed at all to work with PageReferences and PageData is a bit of an issue though. It kind of sends a signal that the CMS vendor is not particularly interested in unit testing.

  4. Anders Hattestad's avatar

    Anders Hattestad 1 years ago

    I agree that most methods/properties should be virtual. Framework like episerver should make life easier for us programmers.

    But for testing, LinkURL have some issues (language as one of them), and the test should aim to find these. So to rewrite the LinkURL property would not solve this.

  5. Joel Abrahamsson's avatar

    Joel Abrahamsson 1 years ago

    Anders,

    In a integration testing scenario which is what I guess you're thinking about it's relevant to test the full interaction, including what's going on in LinkURL but not when it comes to unit testing.

    In the context of unit testing where we only want to test a single unit of code it's important to be able to isolate that unit from it's dependencies, in this case the logic in LinkURL.

    For instance the logic in my presenter is that it should get the LinkURL from the page, what that URL is is irrelevant in the context of testing that logic.

    I definitely think a framework should allow us to isolate our code from it's implementations and I know EPiServer is working on that when it comes to DataFactory. However, they will never be able to add interfaces for everything (and I don't think I would want an IPageData) so defaulting to virtual would be a simple solution.

  6. Anders Hattestad's avatar

    Anders Hattestad 1 years ago

    I see your point, and to unit test some code maybe the dependecy properties isn't a issue. But if you get the wrong links it is a issue in that part of the code :)

    To add virtual to most methods/properties is in my option a must in a framework. Make stuff a lot easier to modify and test.

    But the best solution in this example would to let the code inside LinkUrl to be sort of like the code for Property[xx]. So we can modify the behaiver of the code, and you could make your own dummy implementasion of LinkUrl to return whatever link you want

Follow me on Twitter

  1. @unclebobmartin Because code coverage is a number that management can measure? 13 hours ago
  2. I'm amazed. "oikeinkirjoitusehdotuksista" is an actual word in the Finnish language! 13 hours ago
  3. @tednyberg Amen to that! 14 hours ago
follow me

Latest comments

  1. Per Ivansson wrote "We will definitely try to release as continiously as we poss..." on On selling 200OK and Truffler to EPiServer
  2. Joel Abrahamsson wrote "Thanks Andreas! Regarding your questions it's not really ..." on On selling 200OK and Truffler to EPiServer
  3. Andreas R wrote "Congrats on the sale. Hope ur rolling around in cash now ;) ..." on On selling 200OK and Truffler to EPiServer

About this site

This blog is built with EPiServer Community, EPiServer CMS, ASP.NET MVC and a bunch of other great products. The source code is available for download at the projects page, where you also can read more about this site and my other projects.

read more