views:

299

answers:

2

This is a tough one because not too many people use Pex & Moles or so I think (even though Pex is a really great product - much better than any other unit testing tool)

I have a Data project that has a very simple model with just one entity (DBItem). I've also written a DBRepository within this project, that manipulates this EF model. Repository has a method called GetItems() that returns a list of business layer items (BLItem) and looks similar to this (simplified example):

public IList<BLItem> GetItems()
{
    using (var ctx = new EFContext("name=MyWebConfigConnectionName"))
    {
        DateTime limit = DateTime.Today.AddDays(-10);
        IList<DBItem> result = ctx.Items.Where(i => i.Changed > limit).ToList();
        return result.ConvertAll(i => i.ToBusinessObject());
    }
}

So now I'd like to create some unit tests for this particular method. I'm using Pex & Moles. I created my moles and stubs for my EF object context.

I would like to write parametrised unit test (I know I've first written my production code, but I had to, since I'm testing Pex & Moles) that tests that this method returns valid list of items.

This is my test class:

[PexClass]
public class RepoTest
{
    [PexMethod]
    public void GetItemsTest(ObjectSet<DBItem> items)
    {
        MEFContext.ConstructorString = (@this, name) => {
             var mole = new SEFContext();
        };

        DBRepository repo = new DBRepository();
        IList<BLItem> result = repo.GetItems();

        IList<DBItem> manual = items.Where(i => i.Changed > DateTime.Today.AddDays(-10));

        if (result.Count != manual.Count)
        {
            throw new Exception();
        }
    }
}

Then I run Pex Explorations for this particular parametrised unit test, but I get an error path bounds exceeded. Pex starts this test by providing null to this test method (so items = null). This is the code, that Pex is running:

[Test]
[PexGeneratedBy(typeof(RepoTest))]
[Ignore("the test state was: path bounds exceeded")]
public void DBRepository_GetTasks22301()
{
    this.GetItemsTest((ObjectSet<DBItem>)null);
}

This was additional comment provided by Pex:

The test case ran too long for these inputs, and Pex stopped the analysis. Please notice: The method Oblivious.Data.Test.Repositories.TaskRepositoryTest.b__0 was called 50 times; please check that the code is not stuck in an infinite loop or recursion. Otherwise, click on 'Set MaxStack=200', and run Pex again.

Update attribute [PexMethod(MaxStack = 200)]

Question

Am I doing this the correct way or not? Should I use EFContext stub instead? Do I have to add additional attributes to test method so Moles host will be running (I'm not sure it does now). I'm running just Pex & Moles. No VS test or nUnit or anything else.

I guess I should probably set some limit to Pex how many items should it provide for this particular test method.

A: 

I am just getting to grips with pex also ... my issues surrounded me wanting to use it with moq ;)

anyway ...

I have some methods similar to your that have the same problem. When i increased the max they went away. Presumably pex was satisfied that it had sufficiently explored the branches. I have methods where i have had to increase the timeout on the code contract validation also.

One thing that you should probably be doign though is passing in all the dependant objects as parameters ... ie dont instantiate the repo in the method but pass it in.

A general problem you have is that you are instantiating big objects in your method. I do the same in my DAL classes, but then i am not tryign to unit test them in isolation. I build up datasets and use this to test my data access code against.

I use pex on my business logic and objects.

If i were to try and test my DAL code id have to use IOC to pass the datacontext into the methods - which would then make testing possible as you can mock the data context.

John Nicholas
But isn't that what Stubs and Moles are for? Stubs should create my context so it should work, and Moles would allow me to inject whatever data I'd need.
Robert Koritnik
yes it is, however if you design your objects so that you pass the dependant objects in then life in general becomes a lot simpler. You can then tell pex which o f the objects being passed in is the one you want to test and all of a sudden it doesnt waste time trying to figure out how a data context works. IOC is a design decision not something you shuold try to switch on later. Its how the documentation for PEX suggests you do it as far as i can tell.
John Nicholas