vendredi 29 mars 2019

C# Shall I make my windows form event related private functions public just for testing purpose?

This might be a very generic question about how to do the unit test for windows form application and with async functions.

I am writing the unit test case for a windows form application which has the async function everywhere.

I have all the event handler functions, for example, button click event function, private. I need to test these functions but I cannot call these functions directly outside to test them.

I tried to fire the event function from the unit test code via calling PerformClick(). It works fine with generic function but does not work properly with async function as I think PeformClick() doesn't await and I cannot verify the result in the testing code.

Here is a simple example of my code. We have two-layout structures. Form class to have only the form design. Form presenter to hold all the logic of functions. I need to test the BtnApplyChangeClick function in the presenter class.

public interface IStandForm
{
    Control.ControllCollections controls {get;}
}
public partial class Form1 : Form, IStandardForm
{
   public Form1()
   {
        InitializeComponent(); // It has a button called BtnDelete
   }
   public Control.ControlCollection controls
   {
        return this.Controls;
   }
}

public class FormPresenter
{   
    IStandardForm myForm;
    IDBController dbController;
    public FormPresenter(IStandardForm form, IDBController dbController)
    {
       this.myForm = form;
       this.dbController = dbController;

       //Assign the event to the button
       Button BtnDelete= (Button)myForm.Controls["BtnDelete"];
       BtnDelete.Click += new System.EventHandler(BtnDeleteClick);
    }

    private async void BtnDeleteClick(object sender, EventArgs e)
    {
        //some validation code   

       //Call db delete
        await dbController.Delete();  
    }
}

//Test Code
[TestFixture]
public class TestFormLogin
{
    [Test]
    public async Task Delete_With_Exception()
    {            
        Mock<IDbController> mockDbController = new Mock<IDbController>();
        mockDbController.Setup(c => c.Delete()).ThrowAsync<Exception>(new Exception("Test Exception"));
        IStandardForm myForm = new Form1;

        FormPresenter = new FormPresenter(mockDbController.Object, myForm);
        Button BtnDelete=(Button)myForm.Controls["BtnDelete"];

        Action act = () => BtnDelete.PerformClick();

        //This assertion will be failed as PeformClick won't wait
        act.Should().Throw<Exception>();  
    }
}

The last line Exception assertion won't work. If I could call event handler function BtnDeleteClick the assertion will be fine.

Would that be a bad idea to just simply make the private event handler function to be public just for testing purpose? It will make my life easier but doesn't sound make sense.

Aucun commentaire:

Enregistrer un commentaire