-1

how to do unit testing for windows form application. I have create Form2 and i want test that form using nUnit , i got this error :

Message: System.TypeInitializationException : The type initializer for '...Form2' threw an exception. ----> System.Threading.ThreadStateException : ActiveX control '8856f961-340a-11d0-a96b-00c04fd705a2' cannot be instantiated because the current thread is not in a single-threaded apartment.

Test

[TestFixture,SingleThreaded]
public class FormTest
{

    [SetUp]
    public void Setup()
    {

    }
    [Test]
    public void Form_Test()
    {
        var form = new Form2();

    }
}

code : Form2

public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();
    }

    public void SomeThing()
    { 

    //something
    }
}

code : Form2.Designer

partial class Form2
{
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Windows Form Designer generated code

    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        this.webBrowser1 = new System.Windows.Forms.WebBrowser();
        this.SuspendLayout();
        // 
        // webBrowser1
        // 
        this.webBrowser1.Dock = System.Windows.Forms.DockStyle.Fill;
        this.webBrowser1.Location = new System.Drawing.Point(0, 0);
        this.webBrowser1.MinimumSize = new System.Drawing.Size(20, 20);
        this.webBrowser1.Name = "webBrowser1";
        this.webBrowser1.Size = new System.Drawing.Size(800, 450);
        this.webBrowser1.TabIndex = 0;
        // 
        // Form2
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(800, 450);
        this.Controls.Add(this.webBrowser1);
        this.Name = "Form2";
        this.Text = "Form2";
        this.ResumeLayout(false);

    }

    #endregion

    private System.Windows.Forms.WebBrowser webBrowser1;
}
sujan maharjan
  • 119
  • 2
  • 3
  • 14

2 Answers2

1

You don't. You don't unit test your Windows with all the logic backed into it. You extract a piece you'd like to test into some class or, even better, an interface and instantiate test targeting that particular instance. That's why it called a "unit" test: on the contrary to the "integration" or "end2end" test, it is responsible for testing standalone pieces of software apart from an outter world.

In addition to this, it is literally useless to test that new form indeed gets created. Better focus on your domain logic, which is always a main source of bugs and undesired effects.

Zazaeil
  • 3,900
  • 2
  • 14
  • 31
0

Exception error is pretty clear:

cannot be instantiated because the current thread is not in a single-threaded apartment.

Add SingleThreaded attribute to test fixture to tell Nunit to run test on single thread.
UI controls must to be execute on single thread.

[TestFixture, SingleThreaded]
public class FormTest
{
    public void Form_Test()
    {
        var form = new Form1();

    }
}

Don't try to categorize tests (unit, integrations, acceptance, feature, behaviour, e2e etc).
There are only two test categories Quick and Slow

Quick: are tests which executes fast, so developer can get feedback on written code as quick as possible.
Slow: are tests which executes slow, at this moment this is tests which touches some external resources (database, file system, web services or UI components).

Slow tests are slow to write and slow to run, but they provide important value in form of confidence that application works as expected.

Possibly in the future external resources can be accessed instantly, which provide possibility to write tests for whole application without mocking every single "unit".

For example these days database can be run "in-memory", which provide possibility to run tests without full mocking of data layer.

In your specific scenario, there are some libraries which allow you to test winforms application in convenient way, just search for it.

You can test Form class without UI as other normal classes, but as soon you try to touch UI component your tests will fail.

If you have some logic in the form, which can be executed without UI components being involved, move this logic in separate class and test this class on it's own.

Fabio
  • 31,528
  • 4
  • 33
  • 72