views:

100

answers:

2

I'm relatively new to TDD, and still trying to learn to apply some of the concepts. Here's my situation.

I've got a WinForm with a DataGridView. I'm trying to write a test for the routine to be called by a button click that will perform some operations on the selected rows of the grid. So I will be passing in the DataGridViewSelectedRowCollection object (i.e, the dgv.SelectedRows property at the time the button is clicked).

The DataGridViewSelectedRowCollection object has no constructor, so the only way I can figure to create it is to put together a DataGridView in my test project, then select some rows and pass in the SelectedRows property. But clearly, I don't want to re-create the whole form there.

So I do a DataGridView dgv = new DataGridView(), and gin up a BindingList (actually a SortableBindingList) just like the grid is bound to in the real application. The test list has 3 rows in it. And I do a dgv.DataSource = myList.

Now, at that point in the real application, the grid view is bound. If I look at dgv.Rows.Count, it's equal to the number of rows in the list. However, in my test, setting the DataSource property to the list still results in zero rows in the grid.

I'm thinking there's something missing in the creation of the gridview that normally gets done when it's added to the control list of the form. It probably initializes the handler for the OnDataSourceChanged event or something, and that isn't being done in my test code, but I'm really at a loss as to how to fix it, again, without re-creating a whole form object in my test fixture.

Here's the relavant code form my test method:

        DataGridView residueGrid = new DataGridView();
        List<Employee> baseListToGrid = new List<Employee>();
        SortableBindingList<Employee> listToGrid = new SortableBindingList<Employee>(baseListToGrid);
        residueGrid.DataSource = listToGrid;
        for (int ix = 1; ix < 4; ix++)
        {
             listToGrid.Add(ObjectMother.GetEmployee(ix));
        }
        Assert.AreEqual(3, listToGrid.Count, "SortableBindingList does not have correct count");
        Assert.AreEqual(3, residueGrid.Rows.Count, "DataGrid is not bound to list");

Thanks for any help you can give me.

A: 
DataGridView residueGrid = new DataGridView();
List<Employee> baseListToGrid = new List<Employee>();
SortableBindingList<Employee> listToGrid = new SortableBindingList<Employee>(baseListToGrid);

// residueGrid.DataSource = listToGrid; <-- move this line...

for (int ix = 1; ix < 4; ix++)
{
     listToGrid.Add(ObjectMother.GetEmployee(ix));
}

// residueGrid.DataSource = listToGrid; <-- ...to here!

Assert.AreEqual(3, listToGrid.Count, "SortableBindingList does not have correct count");
Assert.AreEqual(3, residueGrid.Rows.Count, "DataGrid is not bound to list");

A useful structure for writing test is the following:

public void MyTest()
{
    // Arrange
    // Act
    // Assert
}

In this case, Arrange would be instantiating all the objects, and filling the list. Act is where you set the data source of the gridview, and Assert is where you check that everything went OK. I usually write out those three comment lines each time I start writing a test.

Tomas Lycken
Thomas, thanks for taking the time to respond.A) I am using the A/A/A model. The code that I posted is all part of the Arrange step. I just put in the asserts there so that I could be sure of my preconditions.B) I've tried it with the binding after populating the list, and the result is the same. The grid doesn't get bound, which is the real question that I'm asking here.
Dave Hanna
I just re-read the response and my comment, and realized that perhaps I wasn't clear.All this code is NOT what I'm testing. I'm testing a routine that gets called with the selected rows from the datagrid. All this code is part of the "Arrange" to create the DataGridViewSelectedRowCollection to pass to the method under test.
Dave Hanna
A: 

Well, I solved the problem, and pretty much confirmed that it is something being done in the initialization of the control when added to the form that makes the DataSource binding work.

It suddenly dawned on me that that the "target" created by the MS testing framework is a private accessor to the Form itself. So I changed the line DataGridView residueGrid = new DataGridView(); in the above code to, instead of creating a new DGV object, just reference the one on the target form: DataGridView residueGrid = target.residueGrid;

That change made everything work as expected.

Dave Hanna